Time Limit: 2000MS | Memory Limit: 20000K | |
Total Submissions: 5906 | Accepted: 1622 |
Description
Input
Output
Sample Input
3 1 3 1 1 0 1 1 1 0 1 1
Sample Output
1 2
如果单纯是求割点数的话。。。这个题不难。。直接拆点然后最大流处理一下就可以了。。问题是这个题要求按照字典序(依题意推出来的)把最少的割点输出来。。。。。大概思路就是 。。。枚举每个点,除去该点后。。。新建图。。然后看所求的最大流有没有减少。。。。来判断每个点是不是割点。。。。然后保存枚举的割点。。就可以了。。
#include<iostream> #include<cstdio> #include<cstring> using namespace std; #define inf 1000000000 #define maxM 500 #define maxN 150000 struct node{ int u,v,f,next; }edge[maxN]; int head[maxM],p,lev[maxM],cur[maxM]; int que[maxM]; inline void init1(){ p=0;memset(head,-1,sizeof(head)); } bool bfs(int s,int t){ int qin=0,qout=0,i,u,v; memset(lev,0,sizeof(lev)); lev[s]=1,que[qin++]=s; while(qout!=qin){ u=que[qout++]; for(i=head[u];i!=-1;i=edge[i].next) if(edge[i].f>0 && lev[v=edge[i].v]==0){ lev[v]=lev[u]+1,que[qin++]=v; if(v==t){ qout=qin;break; } } } return lev[t]; } int dinic(int s,int t){ int u,i,f,k,qin; int flow=0; while(bfs(s,t)){ memcpy(cur,head,sizeof(head)); u=s;qin=0; while(1){ if(u==t){ for(k=0,f=inf;k<qin;k++) if(edge[que[k]].f<f) f=edge[que[i=k]].f; for(k=0;k<qin;k++) edge[que[k]].f-=f,edge[que[k]^1].f+=f; flow+=f,u=edge[que[qin=i]].u; } for(i=cur[u];cur[u]!=-1;i=cur[u]=edge[cur[u]].next) if(edge[i].f>0 && lev[u]+1==lev[edge[i].v]) break; if(cur[u]!=-1) que[qin++]=cur[u],u=edge[cur[u]].v; else{ if(qin==0) break; lev[u]=-1,u=edge[que[--qin]].u; } } } return flow; } void addedge(int u,int v,int f){ edge[p].u=u,edge[p].v=v,edge[p].f=f,edge[p].next=head[u];head[u]=p++; edge[p].u=v,edge[p].v=u,edge[p].f=0,edge[p].next=head[v],head[v]=p++; } int main(){ int n,s,t,flow; int i,j,vis[maxM],map[500][500],ans[maxM],ain; while(scanf("%d%d%d",&n,&s,&t)!=-1){ init1();ain=0; memset(vis,0,sizeof(vis)); for(i=1;i<=n;i++) if(i!=s && i!=t) addedge(i,i+n,1); else addedge(i,i+n,inf); for(i=1;i<=n;i++) for(j=1;j<=n;j++){ scanf("%d",&map[i][j]); if(map[i][j] && j!=s && i!=t && i!=j) // 这里的条件判断是重点 addedge(i+n,j,inf); } if(map[s][t]){ printf("NO ANSWER!\n"); continue; } flow=dinic(s,t+n); for(i=1;i<=n;i++){ if(i==s || i==t) continue; vis[i]=1; init1(); for(j=1;j<=n;j++) if(vis[j]) continue; else if(j!=s && j!=t) addedge(j,j+n,1); else addedge(j,j+n,inf); for(j=1;j<=n;j++) for(int k=1;k<=n;k++){ if(map[j][k] && k!=j && j!=t && k!=s && !vis[j] && !vis[k])//同样是重点 addedge(j+n,k,inf); } int tmp=dinic(s,t+n); if(tmp<flow) ans[ain++]=i,flow=tmp; else vis[i]=0; } printf("%d\n",ain); for(i=0;i<ain-1;i++) printf("%d ",ans[i]); if(ain>0) printf("%d\n",ans[ain-1]); } return 0; }