『干货图论模板』
<更新提示>
<第一次更新>这是一篇记录图论模板的博客
<正文>
最短路篇
Dijkstra
#include<bits/stdc++.h>
using namespace std;
const int N=500000,M=1000000;
struct node
{
int index,val;
bool operator <(const node temp)const
{
return this->val<temp.val;
}
bool operator >(const node temp)const
{
return this->val>temp.val;
}
};
struct edge
{
int ver,val,next;
}e[M*2];
int n,m,dis[N],vis[N],Last[M*2],t,begin;
inline void insert(int x,int y,int v)
{
e[++t].ver=y;e[t].val=v;e[t].next=Last[x];Last[x]=t;
}
inline void dijkstra(void)
{
memset(vis,0x00,sizeof vis);
memset(dis,0x3f,sizeof dis);
priority_queue< node,vector< node >,greater< node > > Heap;
Heap.push((node){begin,0});
dis[begin]=0;
while(!Heap.empty())
{
int temp=Heap.top().index;
Heap.pop();
if(vis[temp])continue;
vis[temp]=true;
for(int i=Last[temp];i;i=e[i].next)
{
int ver=e[i].ver;
if(dis[ver]>dis[temp]+e[i].val)
{
dis[ver]=dis[temp]+e[i].val;
Heap.push((node){ver,dis[ver]});
}
}
}
}
int main(void)
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int x,y,v;
scanf("%d%d%d",&x,&y,&v);
insert(x,y,v);
insert(y,x,v);
}
scanf("%d",&begin);
dijkstra();
for(int i=1;i<=n;i++)
printf("The distence from %d to %d is %d\n",begin,i,dis[i]);
return 0;
}
SPFA
#include<bits/stdc++.h>
using namespace std;
const int N=500000,M=1000000;
struct edge
{
int ver,val,next;
}e[M*2];
int n,m,dis[N],vis[N],Last[M*2],t,begin;
inline void insert(int x,int y,int v)
{
e[++t].ver=y;e[t].val=v;e[t].next=Last[x];Last[x]=t;
}
inline void spfa(void)
{
memset(vis,0x00,sizeof vis);
memset(dis,0x3f,sizeof dis);
queue < int > q;
dis[begin]=0;vis[begin]=true;
q.push(begin);
while(!q.empty())
{
int temp=q.front();
q.pop();
vis[temp]=false;
for(int i=Last[temp];i;i=e[i].next)
{
int ver=e[i].ver;
if(dis[ver]>dis[temp]+e[i].val)
{
dis[ver]=dis[temp]+e[i].val;
if(!vis[ver])
{
q.push(ver);
vis[ver]=true;
}
}
}
}
}
int main(void)
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int x,y,v;
scanf("%d%d%d",&x,&y,&v);
insert(x,y,v);
insert(y,x,v);
}
scanf("%d",&begin);
spfa();
for(int i=1;i<=n;i++)
printf("The distence from %d to %d is %d\n",begin,i,dis[i]);
return 0;
}
最小生成树篇
Prim
#include<bits/stdc++.h>
using namespace std;
const int N=500000,M=1000000;
struct node
{
int index,val;
bool operator <(const node temp)const
{
return this->val<temp.val;
}
bool operator >(const node temp)const
{
return this->val>temp.val;
}
};
struct edge
{
int ver,val,next;
}e[M*2];
int n,m,dis[N],vis[N],Last[M*2],t,ans;
inline void insert(int x,int y,int v)
{
e[++t].ver=y;e[t].val=v;e[t].next=Last[x];Last[x]=t;
}
inline void prim(void)
{
memset(vis,0x00,sizeof vis);
memset(dis,0x3f,sizeof dis);
priority_queue< node,vector< node >,greater< node > > Heap;
Heap.push((node){1,0});
dis[1]=0;
while(!Heap.empty())
{
node temp=Heap.top();
Heap.pop();
if(vis[temp.index])continue;
vis[temp.index]=true;
ans+=temp.val;
int T=temp.index;
for(int i=Last[T];i;i=e[i].next)
{
int ver=e[i].ver;
if(dis[ver]>e[i].val)
{
dis[ver]=e[i].val;
Heap.push((node){ver,dis[ver]});
}
}
}
}
int main(void)
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int x,y,v;
scanf("%d%d%d",&x,&y,&v);
insert(x,y,v);
insert(y,x,v);
}
prim();
printf("%d\n",ans);
return 0;
}
Kruscal
#include<bits/stdc++.h>
using namespace std;
const int N=500000,M=1000000;
struct Link{int x,y,val;}e[M];
int n,m,ans,f[N];
inline bool cmp(Link p1,Link p2){return p1.val<p2.val;}
inline int find(int x){return f[x]==x?x:f[x]=find(f[x]);}
inline void kruscal(void)
{
int cnt=0;
for(int i=1;i<=n;i++)
f[i]=i;
sort(e+1,e+m+1,cmp);
for(int i=1;i<=m;i++)
{
int x=find(e[i].x),y=find(e[i].y);
if(x==y)continue;
f[x]=y;
ans+=e[i].val;
if(++cnt==n-1)break;
}
}
int main(void)
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].val);
kruscal();
printf("%d\n",ans);
return 0;
}
树上问题篇
LCA
#include<cstdio>
#include<cstring>
#include<iostream>
#define mset(name,val) memset(name,val,sizeof name)
using namespace std;
const int N=30000+20,MaxlogN=30;
int n,Last[N],t,askx,asky,depth[N],f[N][MaxlogN],root=0,vis[N];
struct edge{int ver,next;}e[N];
inline void insert(int x,int y)
{
e[++t].ver=y;e[t].next=Last[x];Last[x]=t;
}
inline void input(void)
{
scanf("%d",&n);
for(int i=1;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
insert(x,y);
vis[y]=1;
}
scanf("%d%d",&askx,&asky);
for(int i=1;i<=n;i++)
{
if(!vis[i])
{
root=i;
break;
}
}
}
inline void init(int x,int dep)
{
depth[x]=dep;
for(int i=Last[x];i;i=e[i].next)
{
int y=e[i].ver;
if(f[x][0]==y)continue;
f[y][0]=x;
init(y,dep+1);
}
}
inline void dp(void)
{
f[root][0]=-1;
for(int k=1;(1<<k)<n;k++)
{
for(int i=1;i<=n;i++)
{
if(f[i][k-1]<0)f[i][k]=-1;
else f[i][k]=f[f[i][k-1]][k-1];
}
}
}
inline int LCA(int x,int y)
{
if(depth[x]>depth[y])x^=y^=x^=y;
for(int d=depth[y]-depth[x],i=0;d;d>>=1,i++)
if(d&1)y=f[y][i];
if(x==y)return x;
for(int i=MaxlogN-1;i>=0;i--)
{
if(f[x][i]!=f[y][i])
{
x=f[x][i];
y=f[y][i];
}
}
return f[x][0];
}
inline void reset(void)
{
mset(Last,0);
mset(e,0);
mset(depth,0);
mset(f,0);
mset(vis,0);
t=0;
}
signed main(void)
{
int T;
scanf("%d",&T);
while(T--)
{
reset();
input();
init(root,0);
dp();
printf("%d\n",LCA(askx,asky));
}
return 0;
}
树的直径BFS
#include<cstdio>
#include<iostream>
#include<queue>
#include<vector>
#include<cstring>
#define mset(name,val) memset(name,val,sizeof name)
using namespace std;
const int N=40000+50;
int n,m,ans,vis[N],dis[N];
struct edge{int val,ver;};
vector < edge > Link[N];
inline void input(void)
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int x,y,v;
scanf("%d%d%d",&x,&y,&v);
Link[x].push_back((edge){v,y});
Link[y].push_back((edge){v,x});
}
}
inline int Search(int start)
{
queue< int >q;
mset(vis,0x00);
mset(dis,0x00);
vis[start]=1;
q.push(start);
while(!q.empty())
{
int temp=q.front();q.pop();
for(int i=0;i<Link[temp].size();i++)
{
if(!vis[Link[temp][i].ver])
{
vis[Link[temp][i].ver]=true;
dis[Link[temp][i].ver]=dis[temp]+Link[temp][i].val;
q.push(Link[temp][i].ver);
}
}
}
int res=0,Maxdis=0;
for(int i=1;i<=n;i++)
{
if(dis[i]>Maxdis)
{
Maxdis=dis[i];
res=i;
}
}
return res;
}
int main(void)
{
input();
int p=Search(1);
printf("%d\n",dis[Search(p)]);
return 0;
}
树的直径DP
#include<cstdio>
#include<iostream>
#include<vector>
#include<cstring>
#define mset(name,val) memset(name,val,sizeof name)
using namespace std;
const int N=40000+50;
int n,m,ans,vis[N],d[N],f[N];
struct edge{int val,ver;};
vector < edge > Link[N];
inline void input(void)
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int x,y,v;
scanf("%d%d%d",&x,&y,&v);
Link[x].push_back((edge){v,y});
Link[y].push_back((edge){v,x});
}
}
inline int dp(int x)
{
vis[x]=true;
for(int i=0;i<Link[x].size();i++)
{
int y=Link[x][i].ver;
if(!vis[y])
{
dp(y);
f[x]=max(f[x],d[x]+d[y]+Link[x][i].val);
d[x]=max(d[x],d[y]+Link[x][i].val);
}
}
ans=max(ans,f[x]);
}
int main(void)
{
input();
dp(1);
printf("%d\n",ans);
return 0;
}
树的重心
#include<cstdio>
#include<iostream>
#include<queue>
#include<vector>
#include<cstring>
#define mset(name,val) memset(name,val,sizeof name)
using namespace std;
const int N=20000+50;
int n,size[N],Max[N],ans,cnt;
vector < int > Link[N];
inline void input(void)
{
scanf("%d",&n);
for(int i=1;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
Link[x].push_back(y);
Link[y].push_back(x);
}
}
inline void dp(int r,int f)
{
size[r]=1;
for(int i=0;i<Link[r].size();i++)
{
int Son=Link[r][i];
if(Son==f)continue;
dp(Son,r);
size[r]+=size[Son];
Max[r]=max(Max[r],size[Son]);
}
Max[r]=max(Max[r],n-size[r]);
if(Max[r]==Max[ans]&&r<ans)ans=r;
if(Max[r]<Max[ans])ans=r;
}
int main(void)
{
Max[0]=0x3f3f3f3f;
input();
dp(1,0);
printf("%d\n",ans);
}
树上差分(点)
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int N=100000+200,K=200000+200,MaxlogN=30;
int n,k,cnt[N],depth[N],Last[N*2],t,f[N][MaxlogN],ans=0;
struct edge{int ver,next;}e[N*2];
inline void insert(int x,int y)
{
e[++t].ver=y;e[t].next=Last[x];Last[x]=t;
}
inline void input(void)
{
scanf("%d%d",&n,&k);
for(int i=1;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
insert(x,y);
insert(y,x);
}
}
inline void init(int x,int dep)
{
depth[x]=dep;
for(int i=Last[x];i;i=e[i].next)
{
int y=e[i].ver;
if(f[x][0]==y)continue;
f[y][0]=x;
init(y,dep+1);
}
}
inline void dp(void)
{
f[1][0]=-1;
for(int k=1;(1<<k)<n;k++)
{
for(int i=1;i<=n;i++)
{
if(f[i][k-1]<0)f[i][k]=-1;
else f[i][k]=f[f[i][k-1]][k-1];
}
}
}
inline int LCA(int x,int y)
{
if(depth[x]>depth[y])
x^=y^=x^=y;
for(int d=depth[y]-depth[x],i=0;d;d>>=1,i++)
if(1&d)y=f[y][i];
if(x==y)return x;
for(int i=MaxlogN-1;i>=0;i--)
{
if(f[x][i]!=f[y][i])
{
x=f[x][i];
y=f[y][i];
}
}
return f[x][0];
}
inline void Mark(void)
{
for(int i=1;i<=k;i++)
{
int x,y;
scanf("%d%d",&x,&y);
cnt[x]++;cnt[y]++;
int lca=LCA(x,y);
cnt[lca]--;
if(lca!=1)cnt[f[lca][0]]--;
}
}
inline void Get_sum(int r)
{
for(int i=Last[r];i;i=e[i].next)
{
int Son=e[i].ver;
if(Son==f[r][0])continue;
Get_sum(Son);
cnt[r]+=cnt[Son];
}
ans=max(ans,cnt[r]);
}
signed main(void)
{
input();
init(1,0);
dp();
Mark();
Get_sum(1);
printf("%d\n",ans);
return 0;
}
树上差分(边)
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int N=100000+200,K=200000+200,MaxlogN=30;
int n,k,cnt[N],depth[N],Last[N*2],t,f[N][MaxlogN],ans=0;
struct edge{int ver,next;}e[N*2];
inline void insert(int x,int y)
{
e[++t].ver=y;e[t].next=Last[x];Last[x]=t;
}
inline void input(void)
{
scanf("%d%d",&n,&k);
for(int i=1;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
insert(x,y);
insert(y,x);
}
}
inline void init(int x,int dep)
{
depth[x]=dep;
for(int i=Last[x];i;i=e[i].next)
{
int y=e[i].ver;
if(f[x][0]==y)continue;
f[y][0]=x;
init(y,dep+1);
}
}
inline void dp(void)
{
f[1][0]=-1;
for(int k=1;(1<<k)<n;k++)
{
for(int i=1;i<=n;i++)
{
if(f[i][k-1]<0)f[i][k]=-1;
else f[i][k]=f[f[i][k-1]][k-1];
}
}
}
inline int LCA(int x,int y)
{
if(depth[x]>depth[y])
x^=y^=x^=y;
for(int d=depth[y]-depth[x],i=0;d;d>>=1,i++)
if(1&d)y=f[y][i];
if(x==y)return x;
for(int i=MaxlogN-1;i>=0;i--)
{
if(f[x][i]!=f[y][i])
{
x=f[x][i];
y=f[y][i];
}
}
return f[x][0];
}
inline void Mark(void)
{
for(int i=1;i<=k;i++)
{
int x,y;
scanf("%d%d",&x,&y);
cnt[x]++;cnt[y]++;
int lca=LCA(x,y);
cnt[lca]-=2;
}
}
inline void Get_sum(int r)
{
for(int i=Last[r];i;i=e[i].next)
{
int Son=e[i].ver;
if(Son==f[r][0])continue;
Get_sum(Son);
cnt[r]+=cnt[Son];
}
ans=max(ans,cnt[r]);
}
signed main(void)
{
input();
init(1,0);
dp();
Mark();
Get_sum(1);
printf("%d\n",ans);
return 0;
}
图的连通性篇
Tarjan割点
#include<bits/stdc++.h>
using namespace std;
const int N=90000,M=150000;
int n,Last[M],t,cutvertex[N],dfn[N],low[N],cnt,m,ans[N],tot;
struct edge{int ver,next;}e[M];
inline void insert(int x,int y)
{
e[++t].ver=y;e[t].next=Last[x];Last[x]=t;
}
inline void input(void)
{
scanf("%d%d",&n,&m);
int x,y;
for(int i=1;i<=m;i++)
{
scanf("%d%d",&x,&y);
if(x^y)insert(x,y),insert(y,x);
}
}
inline void Tarjan(int x,int root)
{
dfn[x]=low[x]=++cnt;
int flag=0;
for(int i=Last[x];i;i=e[i].next)
{
int y=e[i].ver;
if(!dfn[y])
{
Tarjan(y,root);
low[x]=min(low[x],low[y]);
if(low[y]>=dfn[x])
{
flag++;
if(x!=root||flag>1)cutvertex[x]=true;
}
}
else low[x]=min(low[x],dfn[y]);
}
}
int main(void)
{
input();
for(int i=1;i<=n;i++)
if(!dfn[i])Tarjan(i,i);
for(int i=1;i<=n;i++)
{
if(cutvertex[i])
ans[++tot]=i;
}
if(tot)printf("%d\n",tot);
else printf("0\n");
for(int i=1;i<=tot;i++)
printf("%d\n",ans[i]);
}
Tarjan割边
#include<bits/stdc++.h>
using namespace std;
const int N=100000+200,M=300000+200;
int n,m,t=1,Last[M*2],dfn[N],low[N],bridge[N],cnt,tot;
struct edge{int ver,next;}e[M*2];
pair < int,int > ans[N];
inline void insert(int x,int y)
{
e[++t].ver=y;e[t].next=Last[x];Last[x]=t;
}
inline void input(void)
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
insert(x,y);
insert(y,x);
}
}
inline void Tarjan(int x,int inedge)
{
dfn[x]=low[x]=++cnt;
for(int i=Last[x];i;i=e[i].next)
{
int y=e[i].ver;
if(!dfn[y])
{
Tarjan(y,i);
low[x]=min(low[x],low[y]);
if(low[y]>dfn[x])
bridge[i]=bridge[i^1]=true;
}
else if(i!=(inedge^1))
low[x]=min(low[x],dfn[y]);
}
}
int main(void)
{
input();
for(int i=1;i<=n;i++)
if(!dfn[i])Tarjan(i,0);
for(int i=2;i<t;i+=2)
if(bridge[i])
{
if(e[i].ver>e[i^1].ver)swap(e[i].ver,e[i^1].ver);
ans[++tot]=make_pair(e[i].ver,e[i^1].ver);
}
sort(ans+1,ans+tot+1);
for(int i=1;i<=tot;i++)
printf("%d %d\n",ans[i].first,ans[i].second);
return 0;
}
Tarjan强连通分量
#include<bits/stdc++.h>
using namespace std;
const int N=20000+200,M=80000+200;
int n,m,dfn[N],low[N],cnt,Last[M*2],t,inSta[N],size[N],tot;
stack < int > Stack;
struct edge{int ver,next;}e[M*2];
struct connected
{
int len=0;
vector < int > List;
}con[N];
inline bool cmp(connected p1,connected p2)
{
return p1.len>p2.len;
}
inline void insert(int x,int y)
{
e[++t].ver=y;e[t].next=Last[x];Last[x]=t;
}
inline void input(void)
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int a,b,t;
scanf("%d%d%d",&a,&b,&t);
if(t==1)insert(a,b);
else insert(a,b),insert(b,a);
}
}
inline void Tarjan(int x)
{
dfn[x]=low[x]=++cnt;
Stack.push(x);inSta[x]=true;
for(int i=Last[x];i;i=e[i].next)
{
int y=e[i].ver;
if(!dfn[y])
{
Tarjan(y);
low[x]=min(low[x],low[y]);
}
else if(inSta[y])low[x]=min(low[x],dfn[y]);
}
if(low[x]==dfn[x])
{
int top=0;tot++;
while(top!=x)
{
top=Stack.top();
Stack.pop();
con[tot].len++;
con[tot].List.push_back(top);
inSta[top]=false;
}
}
}
inline void print(void)
{
sort(con[1].List.begin(),con[1].List.end());
int T=1,best=1,l=con[1].len;
for(int i=2;i<=tot;i++)
{
if(con[i].len==con[i-1].len)
{
sort(con[i].List.begin(),con[i].List.end());
T++;
}
else break;
}
for(int i=2;i<=T;i++)
{
for(int j=0;j<l;j++)
{
if(con[i].List[j]<con[best].List[j])
{
best=i;
break;
}
else if(con[i].List[j]>con[best].List[j])
break;
}
}
for(int i=0;i<l-1;i++)
printf("%d ",con[best].List[i]);
printf("%d\n",con[best].List[l-1]);
}
int main(void)
{
input();
for(int i=1;i<=n;i++)
if(!dfn[i])Tarjan(i);
sort(con+1,con+tot+1,cmp);
printf("%d\n",con[1].len);
print();
return 0;
}
Tarjan点双连通分量
#include<bits/stdc++.h>
using namespace std;
const int M=500*3,N=1000;
int m,n,Last[N],t,dfn[N],low[N],cnt,T;
long long ans1,ans2=1;
struct edge{int ver,next;}e[M];
vector < int >con[N];
stack < int > Stack;
inline void insert(int x,int y)
{
e[++t].ver=y;e[t].next=Last[x];Last[x]=t;
}
inline bool input(void)
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
insert(x,y);
insert(y,x);
}
return true;
}
inline void Tarjan(int x,int root)
{
dfn[x]=low[x]=++cnt;
Stack.push(x);
if(x==root&&!Last[x])
{
Stack.pop();T++;
con[T].push_back(x);
return;
}
for(int i=Last[x];i;i=e[i].next)
{
int y=e[i].ver;
if(!dfn[y])
{
Tarjan(y,root);
low[x]=min(low[x],low[y]);
if(low[y]>=dfn[x])
{
int top=0;T++;
while(top!=y)
{
top=Stack.top();
Stack.pop();
con[T].push_back(top);
}
con[T].push_back(x);
}
}
else low[x]=min(low[x],dfn[y]);
}
}
int main(void)
{
input();
Tarjan(1,1);
for(int i=1;i<=T;i++)
{
printf("The vertex biconnected component #%d :",i);
for(int j=0;j<con[i].size();j++)
printf("%d ",con[i][j]);
puts("");
}
return 0;
}
Tarjan边双连通分量
#include<bits/stdc++.h>
using namespace std;
const int N=10000,M=40000;
int n,m,Last[M],dfn[N],low[N],cnt,con[N],t=1,tot;
struct edge{int ver,next,flag;}e[M];
inline void insert(int x,int y)
{
e[++t].ver=y;e[t].next=Last[x];Last[x]=t;
}
inline void input(void)
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
insert(x,y);
insert(y,x);
}
}
inline void Tarjan(int x,int inedge)
{
dfn[x]=low[x]=++cnt;
for(int i=Last[x];i;i=e[i].next)
{
int y=e[i].ver;
if(!dfn[y])
{
Tarjan(y,i);
low[x]=min(low[x],low[y]);
if(low[y]>dfn[x])e[i].flag=e[i^1].flag=true;
}
else if(i!=(inedge^1))low[x]=min(low[x],dfn[y]);
}
}
inline void dfs(int x)
{
con[x]=tot;
printf("%d ",x);
for(int i=Last[x];i;i=e[i].next)
{
if(e[i].flag)continue;
int y=e[i].ver;
if(!con[y])dfs(y);
}
}
inline void colored(void)
{
for(int i=1;i<=n;i++)
if(!con[i])
{
++tot;
printf("The Edge biconnected component #%d :",tot);
dfs(i);
puts("");
}
}
int main()
{
input();
Tarjan(1,0);
colored();
return 0;
}
判环篇
Topsort
#include<bits/stdc++.h>
using namespace std;
const int N=500000,M=1000000;
struct edge
{
int ver,next;
}e[M*2];
int n,m,Last[M*2],t,loop,indeg[N],cnt,ans[N];
queue < int > q;
inline void insert(int x,int y)
{
e[++t].ver=y;e[t].next=Last[x];Last[x]=t;
}
inline bool topsort(void)
{
for(int i=1;i<=n;i++)
if(!indeg[i])q.push(i);
while(!q.empty())
{
int temp=q.front();q.pop();ans[++cnt]=temp;
for(int i=Last[temp];i;i=e[i].next)
{
int ver=e[i].ver;
indeg[ver]--;
if(!indeg[ver])q.push(ver);
}
}
return cnt==n;
}
int main(void)
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
insert(x,y);
indeg[y]++;
}
topsort();
if(loop)printf("Impossible\n");
else
for(int i=1;i<=n;i++)
printf("%d ",ans[i]);
puts("");
return 0;
}
<后记>