POJ3436

這是第二道網絡流。。=。=我是有多落後。。這題完全是看的別人的思路,照着別人的代碼敲的。感覺這樣的拆點方式很是巧妙,是按機器的流入流出進行拆點。分爲兩個點。然後再進行連接。開始的時候一直WA。是因爲沒有將爲2的機器某點與源點相連。也沒有將其與匯點相連。只是感受到了網絡流的一點點美很是爽~~而且深刻到認識到我的EK模板的內部的工作方式~~

上代碼:

#include<cstdio>
#include<cstring>
using namespace std;
struct node{
int w,s[15],e[15];
};
node a[60];
int c[200][200],n,m;
int g[200][200];
const int inf=1000000000;
int Edmonds_Karp( int s, int t ){
    int p, q, queue[210], u, v, pre[210], flow= 0, aug;
    while(true){
        memset(pre,-1,sizeof(pre));
        for( queue[p=q=0]=s; p<=q; p++ ){
            u= queue[p];
            for( v=0; v<m&&pre[t]<0; v++ )
                if( c[u][v]>0 && pre[v]<0 )
                    pre[v]=u, queue[++q]=v;
            if( pre[t]>=0 )    break;
        }
        if( pre[t]<0 )    break;
        aug= 99999999;
        for( u=pre[v=t]; v!=s; v=u,u=pre[u] )
            if(c[u][v]<aug)    aug=c[u][v];
        for( u=pre[v=t]; v!=s; v=u,u=pre[u] )
            c[u][v]-=aug, c[v][u]+=aug;
        flow+= aug;
    }
    return flow;
}


main(){
int p,i,j,k,edge,f;
while(scanf("%d%d",&p,&n)!=-1){
//printf("wa\n");
edge=0;
memset(c,0,sizeof(c));
for(i=1;i<=n;i++){
scanf("%d",&a[i].w);
c[i][i+n]=a[i].w;
edge++;
for(j=1;j<=p;j++){
scanf("%d",&a[i].s[j]);
}
for(j=1;j<=p;j++){
scanf("%d",&a[i].e[j]);
}
}
for(i=1;i<=n;i++){
for(j=1;j<=n;j++){
if(i==j)
continue;
int flag=1;
for(k=1;k<=p;k++)
if(a[i].e[k]!=a[j].s[k] && a[j].s[k]!=2){
flag=0;
break;
}
if(flag==1){
edge++;
c[i+n][j]=inf;
}
}
}
for(i=1;i<=n;i++){
int num1=0,num2=0;
for(j=1;j<=p;j++){
if(a[i].s[j]==0 || a[i].s[j]==2)
num1++;
if(a[i].e[j]==1 || a[i].e[j]==2)
num2++;
}
if(num1==p){
c[0][i]=inf;
edge++;
}


if(num2==p){
c[i+n][2*n+1]=inf;
edge++;
}


}
for(i=0;i<=2*n+1;i++){
for(j=0;j<=2*n+1;j++){
g[i][j]=c[i][j];
//printf("%d ",c[i][j]);
}
//printf("\n");
}
m=2*n+2;
n=edge;
//printf("%d %d\n",n,m);
f=Edmonds_Karp(0,m-1);
//for(i=0;i<=m-1;i++){
//for(j=0;j<=m-1;j++){
//printf("%d ",c[i][j]);
//}
//printf("\n");
//}
edge=0;
for(i=(m-2)/2+1;i<=m-2;i++){
for(j=1;j<=(m-2)/2;j++){
if((i-(m-2)/2)!=j &&c[i][j]<g[i][j])
edge++;
}
}
printf("%d %d\n",f,edge);
for(i=(m-2)/2+1;i<=m-2;i++){
for(j=1;j<=(m-2)/2;j++){
if((i-(m-2)/2)!=j && g[i][j]>c[i][j])
printf("%d %d %d\n",i-(m-2)/2,j,g[i][j]-c[i][j]);
}
}
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章