poj3469 - Dual Core CPU

来源:互联网 发布:记忆卡数据恢复 编辑:程序博客网 时间:2024/04/27 21:36

                               想看更多的解题报告:http://blog.csdn.net/wangjian8006/article/details/7870410
                                  转载请注明出处:
http://blog.csdn.net/wangjian8006

题目大意:有两个CPU,现在又n个任务,任务在第A个CPU里面执行所花费Ai代价,在第B个CPU里面执行所花费Bi代价
然后又m个限制,每个限制是a,b,c,说任务a和任务b如果不在一个CPU执行就会多花费c代价。

解题思路:基本上看分成2部分就可以直觉感觉是求最小割,割值就是在平面画一条直线,将所有点分为两部分,然后算图上和这条直线相交的边的权值和。而对于最小割来说,最大流流量就是最小割的容量。
而划分方法,就是将最大流后残余网络中s可以走到的点划为s集合,其余点划为t集合,注意,不是可以走到t的点,因为有可能有一条线上的多条边都流满的情况,这种情况下有些点就无法走到t,而且s也走不到它。

这样建图:一个超级源点指向所有任务,容量为任务点在A上所花的代价,反向边容量为0

然后所有任务点指向一个超级汇点,容量为任务点在B上所花的代价,反向边容量为0
然后多花费代价c,就让a和b之间连一条边,来回的容量都为c

 

/*dinic+邻接表Memory 9952KTime  4844MS*/#include <iostream>#include <queue>using namespace std;#define INF INT_MAX#define MAXE 500000#define MAXV 20100#define min(a,b) (a>b?b:a)typedef struct{int s,t,r,contrary,next;}Edge;Edge edge[MAXE];int n,m,source,sink,edge_sum,maxflow;int head[MAXV],dis[MAXV];void addedge(int x,int y,int c,int flag){edge[edge_sum].s=x;edge[edge_sum].t=y;edge[edge_sum].r=c;edge[edge_sum].contrary=edge_sum+1;edge[edge_sum].next=head[x];head[x]=edge_sum++;edge[edge_sum].s=y;edge[edge_sum].t=x;edge[edge_sum].contrary=edge_sum-1;edge[edge_sum].r=(flag?c:0);edge[edge_sum].next=head[y];head[y]=edge_sum++;}int bfs(){int i,v,tmp;queue <int>q;memset(dis,0,sizeof(dis));dis[source]=1;q.push(source);while(!q.empty()){v=q.front();q.pop();for(i=head[v];i!=-1;i=edge[i].next){tmp=edge[i].t;if(!dis[tmp] && edge[i].r){dis[tmp]=dis[v]+1;if(tmp==sink) return 1;q.push(tmp);}}}return 0;}int dfs(int cur,int cp){if(cur==sink) return cp;int tmp=0,i,a,t;for(i=head[cur];i!=-1 && tmp<cp;i=edge[i].next){a=edge[i].t;if(dis[a]==dis[cur]+1 && edge[i].r){t=dfs(a,min(edge[i].r,cp-tmp));edge[i].r-=t;edge[edge[i].contrary].r+=t;tmp+=t;}}if (!tmp) dis[cur]=-1;//这里代表流已经没了,或者说此路不通return tmp;}void dinic(){maxflow=0;while(bfs()) maxflow+=dfs(source,INF);}int main(){int i,a,b,c;while(~scanf("%d%d",&n,&m)){source=0;sink=n+1,edge_sum=0;memset(head,-1,sizeof(head));for(i=1;i<=n;i++){scanf("%d%d",&a,&b);addedge(source,i,a,0);//这是连的有向边addedge(i,sink,b,0);}for(i=0;i<m;i++){scanf("%d%d%d",&a,&b,&c);addedge(a,b,c,1);//这里连无向边}dinic();printf("%d\n",maxflow);}return 0;}


 

==========================================================================================================

 

 

/*sap+gap+邻接表Memory 8080KTime  2375MS*/#include <iostream>using namespace std;#define INF INT_MAX#define MAXE 500000#define MAXV 20100#define min(a,b) (a>b?b:a)typedef struct{int t,r,contrary,next;}Edge;Edge edge[MAXE];int n,m,source,sink,edge_sum,maxflow;int head[MAXV],dis[MAXV],cur[MAXV],gap[MAXV],pre[MAXV];void addedge(int x,int y,int c,int flag){edge[edge_sum].t=y;edge[edge_sum].r=c;edge[edge_sum].next=head[x];head[x]=edge_sum++;edge[edge_sum].t=x;edge[edge_sum].r=(flag?c:0);edge[edge_sum].next=head[y];head[y]=edge_sum++;}void sap(){int u=pre[source]=source,tmp=INF,v,a;memset(dis,0,sizeof(dis));memset(gap,0,sizeof(gap));for(v=0;v<=n;v++) cur[v]=head[v];gap[source]=n;maxflow=0;while(dis[source]<n){loop:for(v=cur[u];v!=-1;v=edge[v].next){a=edge[v].t;if(dis[u]==dis[a]+1 && edge[v].r>0){cur[u]=v;tmp=min(tmp,edge[v].r);pre[a]=u;u=a;if(u==sink){while(u!=source){u=pre[u];edge[cur[u]].r-=tmp;edge[cur[u]^1].r+=tmp;}maxflow+=tmp;tmp=INF;}goto loop;}}int mind=n;for(v=head[u];v!=-1;v=edge[v].next){a=edge[v].t;if(edge[v].r>0 && mind>dis[a]){cur[u]=v;mind=dis[a];}}if((--gap[dis[u]])==0) break;gap[dis[u]=mind+1]++;u=pre[u];}}int main(){int i,a,b,c;while(~scanf("%d%d",&n,&m)){source=0;sink=n+1,edge_sum=0;memset(head,-1,sizeof(head));for(i=1;i<=n;i++){scanf("%d%d",&a,&b);addedge(source,i,a,0);//这是连的有向边addedge(i,sink,b,0);}for(i=0;i<m;i++){scanf("%d%d%d",&a,&b,&c);addedge(a,b,c,1);//这里连无向边}n+=2;sap();printf("%d\n",maxflow);}return 0;}


 

 

原创粉丝点击