ZOJ 3933(网络流)
2016-04-23 22:43
501 查看
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5693
题目大意:给出两个队伍中的人,使其不同队的组合尽量多,还要最大化女生,其中还有人不愿意跟某个人组队。
我用费用流来做,女生费用为0,男生为1。不同队伍的点之间有边,同一个队的没有边相连,且不愿意组队的两个点也不会有边。
折磨我了半天,找不到超时原因,就按网上题解,把边改成用vector来存就过了。
AC代码:
超时代码:
题目大意:给出两个队伍中的人,使其不同队的组合尽量多,还要最大化女生,其中还有人不愿意跟某个人组队。
我用费用流来做,女生费用为0,男生为1。不同队伍的点之间有边,同一个队的没有边相连,且不愿意组队的两个点也不会有边。
折磨我了半天,找不到超时原因,就按网上题解,把边改成用vector来存就过了。
AC代码:
/*-------------------------------------------------------- Author:log Created Time:2016年04月23日 星期六 12时27分38秒 --------------------------------------------------------*/ #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <vector> #include <stack> #include <queue> #include <map> using namespace std; const int maxn=505; const int inf=0x3f3f3f3f; struct Edge{ int from,to; int f,c,v; Edge(int from,int to,int f,int c,int v):from(from),to(to),c(c),f(f),v(v){} }; vector<Edge>edge; vector<int>G[maxn]; int cot; int st,ed; int n; inline void addedge(int from,int to,int c,int v){ edge.push_back(Edge(from,to,0,c,v)); edge.push_back(Edge(to,from,0,0,-v)); int len=edge.size()-1; G[to].push_back(len); G[from].push_back(len-1); } int fa[maxn]; bool vis[maxn]; int dist[maxn]; bool hate[maxn]; int a[maxn]; int ans1,ans2; queue<int>q; bool SPFA(){ int u; memset(vis,0,sizeof(vis)); memset(fa,-1,sizeof(fa)); for(int i=0;i<=ed;i++)dist[i]=inf; dist[st]=0; vis[st]=true; a[st]=inf; q.push(st); while(!q.empty()){ u=q.front();q.pop(); vis[u]=false; for(int i=0;i<G[u].size();i++){ Edge& e=edge[G[u][i]]; // printf("e.to:%d\n",e.to); // printf("e.c:%d e.f:%d",e.c,e.f); if(e.c>e.f&&dist[e.to]>dist[u]+e.v){ fa[e.to]=G[u][i]; dist[e.to]=dist[u]+e.v; a[e.to]=min(a[u],e.c-e.f); if(!vis[e.to]){ q.push(e.to); vis[e.to]=true; } } } } if(dist[ed]==inf)return false; ans1+=a[ed]; ans2+=dist[ed]*a[ed]; u=ed; while(u!=st){ edge[fa[u]].f+=a[ed]; edge[fa[u]^1].f-=a[ed]; u=edge[fa[u]].from; } return true; } void solve(){ ans1=ans2=0; while(SPFA()); printf("%d %d\n",ans1,2*ans1-ans2); for(int i=0;i<edge.size();i+=2){ if(edge[i].from==0||edge[i].to==ed||edge[i].f==0)continue; printf("%d %d\n",edge[i].from,edge[i].to); } } char ch1[maxn],ch2[maxn]; int main(){ int t; int v; scanf("%d",&t); while(t--){ for(int i=0;i<=ed;i++)G[i].clear(); edge.clear(); scanf("%d",&n); scanf("%s",ch1+1); scanf("%s",ch2+1); int m; st=0,ed=n+1; for(int i=1;i<=n;i++){ if(ch1[i]=='0'){ addedge(st,i,1,0); } else { addedge(i,ed,1,0); } scanf("%d",&m); memset(hate,0,sizeof(hate)); for(int j=1;j<=m;j++){ scanf("%d",&v); hate[v]=true; } if(ch1[i]=='1')continue; v=(ch2[i]=='1'); for(int j=1;j<=n;j++){ if(hate[j]||ch1[i]==ch1[j])continue; addedge(i,j,1,ch2[i]-'0'+ch2[j]-'0'); } } solve(); /* for(int i=0;i<edge.size();i++){ printf("cot:%d from:%d to:%d ",i,edge[i].from,edge[i].to); printf("c:%d f:%d v:%d\n",edge[i].c,edge[i].f,edge[i].v); }*/ } return 0; }
超时代码:
/*-------------------------------------------------------- Author:log Created Time:2016年04月23日 星期六 12时27分38秒 --------------------------------------------------------*/ #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <vector> #include <stack> #include <queue> #include <map> using namespace std; const int maxn=505; const int inf=0x3f3f3f3f; struct Edge{ int from,to,ne; int f,c,v; }e[maxn*maxn]; int head[maxn]; int cot; int st,ed; int n; inline void addedge(int from,int to,int c,int v){ e[cot]=(Edge){from,to,head[from],0,c,v}; head[from]=cot++; e[cot]=(Edge){to,from,head[to],0,0,-v}; head[to]=cot++; } int fa[maxn]; bool vis[maxn]; int dist[maxn]; bool hate[maxn][maxn]; int a[maxn]; int ans1,ans2; queue<int>q; bool SPFA(){ int u; memset(vis,0,sizeof(vis)); memset(fa,-1,sizeof(fa)); for(int i=0;i<=n;i++)dist[i]=inf; dist[st]=0; vis[st]=true; a[st]=inf; q.push(st); while(!q.empty()){ u=q.front();q.pop(); vis[u]=false; for(int i=head[u];i!=-1;i=e[i].ne){ if(e[i].c>e[i].f&&dist[e[i].to]>dist[u]+e[i].v){ fa[e[i].to]=i; dist[e[i].to]=dist[u]+e[i].v; a[e[i].to]=min(a[u],e[i].c-e[i].f); if(!vis[e[i].to]){ q.push(e[i].to); vis[e[i].to]=true; } } } } if(dist[ed]==inf){ return false; } ans1+=a[ed]; ans2+=dist[ed]*a[ed]; u=ed; while(u!=st){ e[fa[u]].f+=a[ed]; e[fa[u]^1].f-=a[ed]; u=e[fa[u]].from; } return true; } void solve(){ ans1=ans2=0; while(SPFA()); printf("%d %d\n",ans1,2*ans1-ans2); for(int i=0;i<cot;i+=2){ if(e[i].from==0||e[i].to==ed||e[i].f==0)continue; printf("%d %d\n",e[i].from,e[i].to); } } char ch1[maxn],ch2[maxn]; int main(){ int t; int v; scanf("%d",&t); while(t--){ for(int i=0;i<maxn;i++)head[i]=-1; cot=0; memset(hate,0,sizeof(hate)); scanf("%d",&n); scanf("%s",ch1+1); scanf("%s",ch2+1); int m; for(int i=1;i<=n;i++){ scanf("%d",&m); for(int j=0;j<m;j++){ scanf("%d",&v); hate[i][v]=true; hate[v][i]=true; } } st=0,ed=n+1; for(int i=n;i>=1;i--){ if(ch1[i]=='0'){ addedge(st,i,1,0); } else { addedge(i,ed,1,0); } if(ch1[i]=='1')continue; v=(ch2[i]=='1'); for(int j=1;j<=n;j++){ if(hate[i][j]||ch1[i]==ch1[j])continue; addedge(i,j,1,ch2[i]-'0'+ch2[j]-'0'); } } n++; solve(); /* for(int i=0;i<cot;i++){ printf("cot:%d from:%d to:%d ",i,e[i].from,e[i].to); printf("c:%d f:%d v:%d\n",e[i].c,e[i].f,e[i].v); }*/ } return 0; }
相关文章推荐
- 简单的四则运算
- 数的奇偶性
- ACMer博客瀑布流分析
- ACM程序设计大赛题目分类
- 计算字符串最后一个单词长度
- ACM网址
- 1272 小希的迷宫
- 1272 小希的迷宫
- hdu 1250 大数相加并用数组储存
- 矩阵的乘法操作
- 蚂蚁爬行问题
- 蚂蚁爬行问题
- 求两个数的最大公约数【ACM基础题】
- 打印出二进制中所有1的位置
- 杭电题目---一只小蜜蜂
- 初学图论-Kahn拓扑排序算法(Kahn's Topological Sort Algorithm)
- 初学图论-Bellman-Ford单源最短路径算法
- 初学图论-DAG单源最短路径算法
- 初学图论-Dijkstra单源最短路径算法
- 初学图论-Dijkstra单源最短路径算法基于优先级队列(Priority Queue)的实现