这题WA得我SB一样.......竟然是声明了一个函数没有调用.....
题意:
在联系网中,去掉最少的联系点使得从S和T无法联系。
赤裸裸的求最小割点集的问题;
建图:
网上都有,就不说了。
怎样找割点呢?在这里变成了割边。
上一题POJ2125用的是DFS,找到集合S,那么分跨S与T集合的边就是割边了。
这么做,对于二分图还是很方便的。这里却行不通了。
前面讲过独立轨的概念,图G独立轨最大条数p(S,T),就是图的点割集的个数。
在每条独立轨的内顶点取一个点,组成的就是点割集了。
这题要求的是字典序最小的点割集,当然。。。 不能那么做了....
先用2B一点的做法,枚举每个割点,如果去掉该点,影响了点割集的数量,那么该点为割点。割点集--。
再继续做,如果没有影响,则该点不在独立轨上或者在前点的同一条独立轨上。
这样,找到所有的独立轨上的字典序最小的割点就好了。
代码十分的坑爹... 1900ms++。看来要换模版了....
#include<iostream> #include<cstdio> #define CC(a) memset( a,0,sizeof(a) ) #define MN 444 #define INF 0x7FFFFFFF template<class T>void inline checkmin( T &a,T b ){ if( a>b||a==-1 ) a=b; } using namespace std; int cap[MN][MN],flow[MN][MN],gap[MN],cur[MN],dis[MN],pre[MN]; int N,s,t; void setG() { CC(cap),CC(flow); for( int i=1;i<=N;i++ ) cap[i][i+N]=1; cap[t+N][t]=cap[s+N][s]=INF; int v; for( int i=1;i<=N;i++ ) for( int j=1;j<=N;j++ ) { scanf("%d",&v); if( i==j ) continue; if(v)cap[i+N][j]=INF; } } int sap() { CC(cur),CC(dis),CC(gap),CC(flow); s+=N; int u=pre[s]=s,maxflow=0,aug=-1; gap[0]=2*N+1; while( dis[s]<=2*N ){ loop: for( int v=cur[u];v<=2*N;v++ ) if( cap[u][v]>flow[u][v] && dis[u]==dis[v]+1 ) { pre[v]=u; cur[u]=v; checkmin( aug,cap[u][v]-flow[u][v] ); u=v; if( v==t ) { maxflow+=aug; //printf("%d",maxflow); for( u=pre[u];v!=s;v=u,u=pre[u] ) flow[u][v]+=aug,flow[v][u]-=aug; aug=-1; } goto loop; } int mind=2*N+1; for( int v=0;v<=2*N;v++ ) if( (cap[u][v]-flow[u][v])>0 && mind>dis[v] ) { mind=dis[v]; cur[u]=v; } if( --gap[dis[u]]==0 ) break; gap[dis[u]=mind+1]++; u=pre[u]; } s-=N; return maxflow; } int main() { int cnt,rec[MN]; while( scanf("%d%d%d",&N,&s,&t)!=EOF ) { setG(); int maxflow=sap(); if( maxflow==INF ) { printf( "NO ANSWER!\n" ); continue; } printf( "%d\n",maxflow ); cnt=0; //printf( "s:%d t:%d\n",s,t ); for( int i=1;i<=N;i++ ) { if( i==s || i==t ) continue; cap[i][i+N]=0; int cur=sap(); //printf( "cur:%d\n",cur ); if( cur<maxflow ) { maxflow--; rec[cnt++]=i; cap[i][i+N]--; } cap[i][i+N]++; if(maxflow==0) break; } for( int i=0;i<cnt;i++ ) if(i)printf(" %d",rec[i]); else printf("%d",rec[i]); printf( "\n" ); } return 0; }