标签:
这次的题全是老爷题yooo~
普通二分图,,,源点向正飞行员连1的边,有取向 :->的正副飞行员连1或inf的边,副飞行员和汇点连1的边,然后跑最大流
源/汇点向飞行员连的边一定要单独建= =
1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 using namespace std; 5 6 #define maxn 105 7 #define maxm 3000 8 #define inf 0x3f3f3f3f 9 int cnt,v[maxm<<1],w[maxm<<1],next[maxm<<1],first[maxn]; 10 int SSS,TTT,q[maxn],dep[maxn]; 11 void add(int st,int end,int val){ 12 v[cnt]=end;w[cnt]=val;next[cnt]=first[st];first[st]=cnt++; 13 v[cnt]=st;w[cnt]=0;next[cnt]=first[end];first[end]=cnt++; 14 } 15 bool bfs(){ 16 int head=0,tail=0; 17 memset(dep,0,sizeof(dep)); 18 q[++tail]=SSS; 19 dep[SSS]=1; 20 while(head<tail){ 21 int x=q[++head]; 22 for(int e=first[x];e!=-1;e=next[e]){ 23 if(!dep[v[e]]&&w[e]>0){ 24 dep[v[e]]=dep[x]+1; 25 q[++tail]=v[e]; 26 } 27 } 28 } 29 return dep[TTT]; 30 } 31 int dfs(int x,int lim){ 32 if(x==TTT)return lim; 33 int lim1=lim; 34 for(int e=first[x];e!=-1;e=next[e]){ 35 if(dep[v[e]]==dep[x]+1&&w[e]>0){ 36 int flow=dfs(v[e],min(lim,w[e])); 37 w[e]-=flow;w[e^1]+=flow; 38 if((lim-=flow)<=0)break; 39 } 40 } 41 if(lim==lim1)dep[x]=0; 42 return lim1-lim; 43 } 44 int main(){ 45 freopen("flyer.in","r",stdin); 46 freopen("flyer.out","w",stdout); 47 int n,n1,a,b; 48 memset(first,-1,sizeof(first)); 49 scanf("%d%d",&n,&n1); 50 SSS=0,TTT=n+1; 51 for(int i=1;i<=n1;i++)add(SSS,i,1); 52 for(int i=n1+1;i<=n;i++)add(i,TTT,1); 53 while(scanf("%d%d",&a,&b)!=EOF)add(a,b,2); 54 int ans=0; 55 while(bfs())ans+=dfs(SSS,inf); 56 printf("%d\n",ans); 57 fclose(stdin); 58 fclose(stdout); 59 return 0; 60 }
最大权闭合子图,666
源点向实验连权值为赞助额的边,实验向仪器连inf的边,仪器向汇点连权值为仪器开销的边,求出最小割。
最小割上的实验边代表不选的实验,因为开销>赞助额,从而使实验边满载;最小割上的仪器边代表要选的仪器,因为开销<=赞助额,从而使仪器边满载
由此可知答案为所有实验边的和减去最小割
1 #include<stdio.h> 2 #include<string.h> 3 #include<vector> 4 #include<ctype.h> 5 using namespace std; 6 #define maxn 2005 7 #define maxm 105000 8 #define inf 0x3f3f3f3f 9 vector<int>poi[maxn]; 10 int cnt,v[maxm<<1],w[maxm<<1],next[maxm<<1],first[maxn],cur[maxn]; 11 int SSS,TTT,dep[maxn],q[maxn],have[maxn],you[maxn]; 12 void read(int i){ 13 char ch=0; 14 while(1){ 15 while(!isdigit(ch)) 16 ch=getchar(); 17 int tmp=0; 18 while(isdigit(ch)){ 19 tmp=tmp*10+ch-‘0‘; 20 ch=getchar(); 21 } 22 poi[i].push_back(tmp); 23 if(ch==‘\r‘)return; 24 } 25 } 26 void add(int st,int end,int val){ 27 v[cnt]=end;w[cnt]=val;next[cnt]=first[st];first[st]=cnt++; 28 v[cnt]=st;w[cnt]=0;next[cnt]=first[end];first[end]=cnt++; 29 } 30 bool bfs(){ 31 int head=0,tail=0; 32 memset(dep,0,sizeof(dep)); 33 q[++tail]=SSS; 34 dep[SSS]=1; 35 while(head<tail){ 36 int x=q[++head]; 37 for(int e=first[x];e!=-1;e=next[e]){ 38 if(!dep[v[e]]&&w[e]>0){ 39 dep[v[e]]=dep[x]+1; 40 q[++tail]=v[e]; 41 } 42 } 43 } 44 return dep[TTT]; 45 } 46 int dfs(int x,int lim){ 47 if(x==TTT)return lim; 48 int lim1=lim; 49 for(int e=cur[x];e!=-1;e=next[e]){ 50 if(dep[v[e]]==dep[x]+1&&w[e]>0){ 51 int flow=dfs(v[e],min(lim,w[e])); 52 cur[x]=e; 53 w[e]-=flow;w[e^1]+=flow; 54 if((lim-=flow)<=0)break; 55 } 56 } 57 if(lim==lim1)dep[x]=0; 58 return lim1-lim; 59 } 60 int main(){ 61 freopen("shuttle.in","r",stdin); 62 freopen("shuttle.out","w",stdout); 63 int n,m,x; 64 memset(first,-1,sizeof(first)); 65 scanf("%d%d",&n,&m); 66 SSS=0,TTT=n+m+1; 67 int sum=0; 68 for(int i=1;i<=n;i++){ 69 scanf("%d",&x); 70 sum+=x; 71 add(SSS,i,x); 72 read(i); 73 } 74 for(int i=1;i<=m;i++){ 75 scanf("%d",&x); 76 add(i+n,TTT,x); 77 } 78 for(int i=1;i<=n;i++) 79 for(int j=0;j<poi[i].size();j++) 80 add(i,poi[i][j]+n,inf); 81 int ans=0; 82 while(bfs()){ 83 memcpy(cur,first,sizeof(first)); 84 ans+=dfs(SSS,inf); 85 } 86 for(int e=first[SSS];e!=-1;e=next[e]) 87 if(dep[v[e]])have[v[e]]=1; 88 for(int i=1;i<=n;i++) 89 if(have[i]){ 90 printf("%d ",i); 91 for(int j=0;j<poi[i].size();j++) 92 you[poi[i][j]]=1; 93 } 94 printf("\n"); 95 for(int i=1;i<=m;i++) 96 if(you[i])printf("%d ",i); 97 printf("\n%d\n",sum-ans); 98 fclose(stdin); 99 fclose(stdout); 100 return 0; 101 }
可以转化成二分图最大匹配,因为每匹配一条边就少一条路径。因为要输出方案,所以写了匈牙利。。。
把每个点拆成两个,原图中有边的两个点之间有配对倾向。路径数为点数-最大匹配数,输出方案就可以在belong数组,或map数组上luogan
1 #include<stdio.h> 2 #include<string.h> 3 4 #define maxn 305 5 #define maxm 6005 6 int cnt,v[maxm<<1],next[maxm<<1],first[maxn]; 7 int used[maxn],belong[maxn],map[maxn],vis[maxn]; 8 9 void add(int st,int end){ 10 v[++cnt]=end; 11 next[cnt]=first[st]; 12 first[st]=cnt; 13 } 14 bool find(int x){ 15 for(int e=first[x];e;e=next[e]){ 16 if(!used[v[e]]){ 17 used[v[e]]=1; 18 if(!belong[v[e]]||find(belong[v[e]])){ 19 belong[v[e]]=x; 20 map[x]=v[e]; 21 return true; 22 } 23 } 24 } 25 return false; 26 } 27 int main(){ 28 freopen("path3.in","r",stdin); 29 freopen("path3.out","w",stdout); 30 int n,m,a,b; 31 scanf("%d%d",&n,&m); 32 for(int i=1;i<=m;i++){ 33 scanf("%d%d",&a,&b); 34 add(a,b+n); 35 } 36 int ans=0; 37 for(int i=1;i<=n;i++){ 38 for(int j=n;j<=2*n;j++)used[j]=0; 39 if(find(i))ans++; 40 } 41 for(int i=1;i<=n;i++){ 42 if(!vis[i]){ 43 int ii=i; 44 while(ii>0){ 45 printf("%d ",ii); 46 vis[ii]=1; 47 ii=map[ii]-n; 48 } 49 printf("\n"); 50 } 51 } 52 printf("%d\n",n-ans); 53 fclose(stdin); 54 fclose(stdout); 55 return 0; 56 }
Dinic算法请见友链中的y7070. http://www.cnblogs.com/y7070/p/4988800.html
标签:
原文地址:http://www.cnblogs.com/Ngshily/p/4988909.html