poj 3155
最小割。
二分方法中:
while(begin<=end)
{
mid=(begin+end)>>1;
build(mid);
if(m*xx-solve()>0) begin=mid+1;
else
end=mid-1;
}
最后 end<ans*<=begin.
最大权值为begin,但要求定点集,要用end。
代码:
#include<iostream> #include<fstream> #include<queue> #define xx 1000000 using namespace std; int n; int c[1110][1110],f[1110][1110]; int d[1110]; int flow; int v[1110]; typedef struct e{ int data; e *next; }e; e edge[1110]; int build(){ int i,j,k; queue<int> q; q.push(1); memset(d,0,sizeof(d)); d[1]=1; while(!q.empty()) { i=q.front(); q.pop(); e *p=edge[i].next; while(p) { j=p->data; if(d[j]==0&&c[i][j]>f[i][j]) { d[j]=d[i]+1; if(j==n) return 1; q.push(j); } p=p->next; } } return 0; } int find(int m,int minw){ int i,k; int j; if(m==n) return minw; v[m]=1; e *p=edge[m].next; while(p) { i=p->data; if(c[m][i]>f[m][i]&&d[i]==d[m]+1&&v[i]==0) { j=find(i,min(minw,c[m][i]-f[m][i])); if(j) { f[m][i]+=j; f[i][m]=-1*f[m][i]; return j; } } p=p->next; } return 0; } int solve(){ int i,j; int k; flow=0; memset(f,0,sizeof(f)); while(build()) while(1){ memset(v,0,sizeof(v)); i=(~0u)>>1; k=find(1,i); flow+=k; if(k==0) break; } return flow; } int ans,m; void build(int mid){ int i; for(i=1+m+1;i<=n-1;i++) c[i][n]=mid; } void dfs(int s){ e *p=edge[s].next; v[s]=1; while(p){ if(v[p->data]==0&&c[s][p->data]>f[s][p->data]) { dfs(p->data); if(p->data>1+m) ans++; } p=p->next; } } void read(){ // ifstream cin("in.txt"); int i,j,k,s,t; cin>>n>>m; // scanf("%d%d",&n,&m); if(m==0) { cout<<1<<endl; cout<<1<<endl; return ; } for(i=1;i<=m;i++) { c[1][i+1]=xx; e*p=new e; p->data=i+1; p->next=edge[1].next; edge[1].next=p; e *q=new e; q->data=1; q->next=edge[i+1].next; edge[i+1].next=q; } for(i=1;i<=n;i++) { e*p=new e; p->data=i+1+m; p->next=edge[m+n+2].next; edge[n+m+2].next=p; e *q=new e; q->data=m+n+2; q->next=edge[i+1+m].next; edge[i+1+m].next=q; } for(i=1;i<=m;i++) { cin>>s>>t; // scanf("%d%d",&s,&t); c[i+1][s+1+m]=(~0u)>>1; e *p=new e; p->data=i+1; p->next=edge[s+1+m].next; edge[s+1+m].next=p; e *q=new e; q->data=s+1+m; q->next=edge[i+1].next; edge[i+1].next=q; c[i+1][t+1+m]=(~0u)>>1; e *p1=new e; p1->data=i+1; p1->next=edge[t+1+m].next; edge[t+1+m].next=p1; e *q1=new e; q1->data=t+1+m; q1->next=edge[i+1].next; edge[i+1].next=q1; } n=n+m+2; int begin,end,mid; begin=0;end=m*xx; while(begin<=end) { mid=(begin+end)>>1; build(mid); if(m*xx-solve()>0) begin=mid+1; else end=mid-1; } for(i=1+m+1;i<=n-1;i++) c[i][n]=end; solve(); memset(v,0,sizeof(v)); ans=0; dfs(1); cout<<ans<<endl; for(i=1+m+1;i<=n-1;i++) { if(v[i]) cout<<i-m-1<<endl; } } int main(){ read(); return 0; }