先写一道,USACO5.4.5telecow求图的最小点割,运用拆点法(同求图的最小路径覆盖),然后求最小割。
我采用了一种流量*6000+序号i的方法,但好像有问题,如果真的要写的话就像上面一道最小割一样在DFS一下。
说明:两种搜索
1.论文中的floodfill(BFS/DFS)求该最大流的最小割。
2.DFS枚举割点,求最大流为0,表示s->t不通(或直接BFS验证不通)。
不知对不对的代码
/**//*
USER:zyn19961
TASK:telecow
LANG:C++
*/
#include<cstdio>
#include<cstring>
#include<fstream>
#include<iostream>
#include<algorithm>
using namespace std;
//
#define MM(a,i) memset(a,i,sizeof(a))
#define FOR(i,l,r) for (int i=(l);i<=(r);i++)
#define DFOR(i,r,l) for (int i=(r);i>=(l);i--)
#define NFOR(i,l,r) for (i=(l);i<=(r);i++)
#define NDFOR(i,r,l) for (i=(r);i>=(l);i--)
#define PFOR(p,a,next) for(int p=a;p;p=next[p])
#define NPFOR(p,a,next) for(p=a;p;p=next[p])
//
typedef long long Int64;
const int INF=~0U>>2;
//
const int maxn=601;
const int maxm=300001;
//
int Q[maxm],H,T;
//
int to[maxm],next[maxm],sc[maxm],snum=0;
int level[maxn],head[maxn],out[maxn];
//
void init();
void insert(int x,int y,int c);
int max_flow(int n,int s,int t);
//
ifstream fin("telecow.in");
ofstream fout("telecow.out");
//
//
int main(){//a in a+n out
int n,m;fin>>n>>m;
int c1,c2;fin>>c1>>c2;
int a,b;init();
FOR(i,1,n)insert(i,i+n,6000+i);
FOR(i,1,m)fin>>a>>b,insert(a+n,b,INF),insert(b+n,a,INF);
int ans=max_flow(n+n,c1+n,c2);
ans/=6000;
fout<<ans<<"\n";
//
bool arr[maxn];MM(arr,false);
H=T=1,Q[H]=c1+n,arr[c1+n]=true;
for(;H<=T;){
PFOR(p,head[Q[H]],next)
if(sc[p]&&!arr[to[p]])T++,Q[T]=to[p],arr[to[p]]=true;
H++;
}
FOR(i,1,n){
if(arr[i]!=arr[i+n]&&i!=c1&&i!=c2)
if(ans>1)fout<<i<<" ",ans--;
else if(ans==1)fout<<i<<"\n",ans--;
else break;
}
//
fout.close();
return 0;
}
void init(){snum=1;MM(head,0);}
void insert(int x,int y,int c){
snum++,to[snum]=y,sc[snum]=c,next[snum]=head[x],head[x]=snum;
snum++,to[snum]=x,sc[snum]=0,next[snum]=head[y],head[y]=snum;}
int max_flow(int n,int s,int t){
int flow=0,cur;
for(;;){MM(level,0);
H=T=1,level[s]=1,Q[H]=s;
for(;H<=T;H++){int &t=Q[H];
PFOR(p,head[t],next)
if(sc[p]&&!level[to[p]])
T++,level[to[p]]=level[t]+1,Q[T]=to[p];}
if(!level[t])break;
FOR(i,1,n)out[i]=head[i];
for(int q=0;;){
if(!q){
NPFOR(cur,out[s],next)
if(sc[cur]&&out[to[cur]]&&level[to[cur]]==2)
break;
if(cur)q++,Q[q]=cur,out[s]=next[cur];
else break;
}
int u=to[Q[q]];
if(u==t){int dd=INF,ddl=0;
FOR(i,1,q)if(sc[Q[i]]<dd)dd=sc[Q[i]],ddl=i;
flow+=dd;
FOR(i,1,q)sc[Q[i]]-=dd,sc[Q[i]^1]+=dd;
FOR(i,1,q)if(!sc[Q[i]]){q=ddl-1;break;}
}
else {
NPFOR(cur,out[u],next)
if(sc[cur]&&out[to[cur]]&&level[u]+1==level[to[cur]])break;
if(cur)q++,Q[q]=cur,out[u]=next[cur];
else out[u]=0,q--;
}
}
}
return flow;
}
另一道是5.3.3schlnet,与图的强连通分量有关。
方法实在太多了,准备一一实现后再深入总结。
1.floyd O(n^3)
2.tarjianO(m+n)
3.dfn-low O(m+n)
4.Kosaraju O((m+n)*2)
我的代码(dfn_low)
/**//*
USER:zyn19961
TASK:schlnet
LANG:C++
*/
#include<cstdio>
#include<cstring>
#include<fstream>
#include<iostream>
#include<algorithm>
using namespace std;
//
#define MM(a,i) memset(a,i,sizeof(a))
#define FOR(i,l,r) for (int i=(l);i<=(r);i++)
#define DFOR(i,r,l) for (int i=(r);i>=(l);i--)
//
typedef long long Int64;
const int INF=~0U>>2;
const int maxn=201;
//
ifstream fin("schlnet.in");
ofstream fout("schlnet.out");
//
int n,a,b;
int G[maxn][maxn];
int dfn[maxn],low[maxn];
int tot=0;
int st=0,stack[maxn];
bool in_stack[maxn];
int set[maxn];
void group(int u);
int map[maxn][maxn];
int totset=0;
int main(){
fin>>n;
MM(in_stack,false),MM(dfn,0),MM(map,0);
FOR(i,1,n){
int a=INF;
for(;a!=0;)
fin>>a,G[i][0]++,G[i][G[i][0]]=a;
G[i][0]--;
}
FOR(i,1,n)if(!dfn[i])group(i);
FOR(i,1,n)
FOR(j,1,G[i][0]){
a=set[i],b=set[G[i][j]];
if(map[a][b]==0&&a!=b){
map[a][b]=1;
map[a][0]++;
map[b][totset+1]++;
}
}
int count1=0,count2=0;
FOR(i,1,totset){
if(map[i][totset+1]==0)count1++;
if(map[i][0]==0)count2++;
}
fout<<count1<<"\n";
if(totset==1)fout<<"0\n";
else fout<<max(count1,count2)<<"\n";
fin.close();
fout.close();
return 0;
}
void group(int u){
tot++;
dfn[u]=low[u]=tot;
st++,stack[st]=u;
in_stack[u]=true;
FOR(i,1,G[u][0]){
int v=G[u][i];
if(!dfn[v]){
group(v);
if(low[v]<low[u])
low[u]=low[v];
}
if(dfn[v]<low[u])
if(in_stack[v])
low[u]=dfn[v];
}
if(dfn[u]==low[u]){
totset++;
for(;stack[st+1]!=u;st--)
set[stack[st]]=totset,in_stack[stack[st]]=false;
}
}