【USACO5.4.5】奶牛的电信
Description
农夫约翰的奶牛们喜欢通过电邮保持联系,于是她们建立了一个奶牛电脑网络,以便互相交流。这些机器用如下的方式发送电邮:如果存在一个由c台电脑组成的序列a1,a2,...,a(c),且a1与a2相连,a2与a3相连,等等,那么电脑a1和a(c)就可以互发电邮。
很不幸,有时候奶牛会不小心踩到电脑上,农夫约翰的车也可能碾过电脑,这台倒霉的电脑就会坏掉。这意味着这台电脑不能再发送电邮了,于是与这台电脑相关的连接也就不可用了。
有两头奶牛就想:如果我们两个不能互发电邮,至少需要坏掉多少台电脑呢?请编写一个程序为她们计算这个最小值和与之对应的坏掉的电脑集合。
以如下网络为例:
1*
/
3 - 2*
这张图画的是有2条连接的3台电脑。我们想要在电脑1和2之间传送信息。电脑1与3、2与3直接连通。如果电脑3坏了,电脑1与2便不能互发信息了。
很不幸,有时候奶牛会不小心踩到电脑上,农夫约翰的车也可能碾过电脑,这台倒霉的电脑就会坏掉。这意味着这台电脑不能再发送电邮了,于是与这台电脑相关的连接也就不可用了。
有两头奶牛就想:如果我们两个不能互发电邮,至少需要坏掉多少台电脑呢?请编写一个程序为她们计算这个最小值和与之对应的坏掉的电脑集合。
以如下网络为例:
1*
/
3 - 2*
这张图画的是有2条连接的3台电脑。我们想要在电脑1和2之间传送信息。电脑1与3、2与3直接连通。如果电脑3坏了,电脑1与2便不能互发信息了。
Input
第一行 四个由空格分隔的整数:N,M,c1,c2.N是电脑总数(1<=N<=100),电脑由1到N编号。M是电脑之间连接的总数(1<=M<=600)。最后的两个整数c1和c2是上述两头奶牛使用的电脑编号。连接没有重复且均为双向的(即如果c1与c2相连,那么c2与c1也相连)。两台电脑之间至多有一条连接。电脑c1和c2不会直接相连。
第2到M+1行 接下来的M行中,每行包含两台直接相连的电脑的编号。
第2到M+1行 接下来的M行中,每行包含两台直接相连的电脑的编号。
Output
输出共有两行。第一行是使电脑c1和c2不能互相通信需要坏掉的电脑数目的最小值。第二行是排好序的坏掉的电脑的编号列表。注意c1和c2都不能坏掉。如果有多种可能情况,输出第一个数最小的一种,如果第一个数相同,则输出第二个数最小的一种,依此类推。
Sample Input
3 2 1 21 32 3
Sample Output
13
Solution
非常类似于
【Baltic2008】黑手党(Mafia)(BSOI2891)http://blog.csdn.net/hwzzyr/article/details/56012697
和
【USACO4.4.2】追查坏牛奶http://blog.csdn.net/hwzzyr/article/details/56017121
CODE
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int inf=0x3f3f3f3f;
struct Pipe{int next,to,flow,f;}pipe[100005];
Pipe tg[100005],ttg[100005];
int h[1005],cnt=1;
inline void add(int x,int y,int z){
pipe[++cnt].to=y;pipe[cnt].next=h[x];h[x]=cnt;pipe[cnt].flow=z;pipe[cnt].f=1;
pipe[++cnt].to=x;pipe[cnt].next=h[y];h[y]=cnt;pipe[cnt].flow=0;pipe[cnt].f=1;
return ;
}
inline int read(){
char c;int rec=0;
while((c=getchar())<'0'||c>'9');
while(c>='0'&&c<='9')rec=rec*10+c-'0',c=getchar();
return rec;
}
int N,M,st,ed,n;
int ans,sum;
int Gap[505],dis[505];
inline int SAP(int v,int maxflow){
if(v==ed)return maxflow;
int temp=maxflow,i,j,p;
for(i=h[v];i;i=pipe[i].next){
if(pipe[i].f==0)continue;
j=pipe[i].to;
if(pipe[i].flow&&dis[v]==dis[j]+1){
p=SAP(j,min(pipe[i].flow,temp));
temp-=p;pipe[i].flow-=p;pipe[i^1].flow+=p;
if(temp==0||dis[st]==n)return maxflow-temp;
}
}
if(--Gap[dis[v]]==0)dis[st]=n;
else Gap[++dis[v]]++;
return maxflow-temp;
}
inline void Get(){
memset(Gap,0,sizeof(Gap));
memset(dis,0,sizeof(dis));
Gap[0]=n;sum=0;
while(dis[st]<n)sum+=SAP(st,inf);
return ;
}
inline void Solve(){
ans=sum;
cout<<ans<<endl;
int i,j;
for(i=1;i<=N;i++){
if(i!=st-N&&i!=ed&&pipe[i*2].f==1){
for(j=1;j<=cnt;j++)tg[j]=pipe[j];
for(j=1;j<=cnt;j++)pipe[j]=ttg[j];
pipe[i*2].f=pipe[i*2+1].f=0;
Get();
if(ans>sum){
cout<<i<<" ";
ttg[i*2].f=ttg[i*2+1].f=0;
ans=sum;
}
else for(j=1;j<=cnt;j++)pipe[j]=tg[j];
}
}
return ;
}
int main(){
N=read();M=read();st=read();ed=read();
int i,x,y;
for(i=1;i<=N;i++)add(i,i+N,1);
for(i=1;i<=M;i++){
x=read();y=read();
add(x+N,y,inf);add(y+N,x,inf);
}
st=st+N;n=N*2;
for(i=1;i<=cnt;i++)ttg[i]=pipe[i];
Get();
Solve();
return 0;
}