码迷,mamicode.com
首页 > 其他好文 > 详细

网络流题目汇集(注:题意翻译以及思路基本都是摘录的别人的(虽然也许有的题目会是自己完全独立做出来的,但是题解一般都不会是自己的,人懒没办法))

时间:2015-05-14 20:19:19      阅读:164      评论:0      收藏:0      [点我收藏+]

标签:

从现在开始把每一个我觉得对我来说有新意的图论题目汇集下来

由于目前基本只会网络流,就先来网络流的吧:

1.hdu2883

题意: 有一个烧烤机,每次最多能烤 m 块肉,现在有 n 个人来买烤肉,每个人到达时间为 si,离开时间为 ei,点的烤肉数量为 ci,点的烤肉所需烘烤时间为 di,

          每个人要烤的肉可以分成若干份在同时烤,问是否存在一种方案可以满足所有顾客的需求。

分析: 将所有的到达时间和结束时间按升序排序,得到 x <= 2n-1 个时间区间。

          建图:

          s为源,t为汇,

          每个顾客i作为一个结点并连边(s, i, ni*ti)

          每个区间j作为一个结点并连边(j, t, (ej-sj)*M),其中sj, ej分别表示区间j的起始时间和终止时间

          对任意顾客i和区间j,若 [sj, ej] 完全包含在 [si, ei] 之中,则连边(i, j, INF)

          若最大流等于 ∑ni*ti 则是 Yes,否则是 No。

这题我是觉得不科学的,比如一组数据:

1 10

1 2 3 5

顾客要的东西要五分钟烤完,然后你特么的让人家等了2分钟就好了,你是怎么做到的呀O__O "…

当然,如果真的要较真的话这题我就不会做了(捂脸)

代码:

技术分享
  1 #include<iostream>
  2 #include<algorithm>
  3 #include<queue>
  4 #include<cstring>
  5 #include<cstdio>
  6 #include<climits>
  7 #define MAXE 370000
  8 #define MAXP 606
  9 #define Max(a,b) a>b?a:b
 10 #define Min(a,b) a<b?a:b
 11 using namespace std;
 12 struct Edge
 13 {
 14     int s,t,f,next;
 15 } edge[MAXE];
 16 struct Cust
 17 {
 18     int start,last,stay;
 19 }cust[MAXP];
 20 int head[MAXP];
 21 int time[MAXP*2];
 22 int stay[MAXP];
 23 int cur[MAXP];
 24 int pre[MAXP];
 25 int stack[MAXE];
 26 int used[MAXP];
 27 int ent;
 28 int n,m,s,t;
 29 int num;
 30 void add(int start,int last,int f)
 31 {
 32     edge[ent].s=start;
 33     edge[ent].t=last;
 34     edge[ent].f=f;
 35     edge[ent].next=head[start];
 36     head[start]=ent++;
 37     edge[ent].s=last;
 38     edge[ent].t=start;
 39     edge[ent].f=0;
 40     edge[ent].next=head[last];
 41     head[last]=ent++;
 42 }
 43 bool bfs(int S,int T)
 44 {
 45     memset(pre,-1,sizeof(pre));
 46     pre[S]=0;
 47     queue<int>q;
 48     q.push(S);
 49     while(!q.empty())
 50     {
 51         int temp=q.front();
 52         q.pop();
 53         for(int i=head[temp]; i!=-1; i=edge[i].next)
 54         {
 55             int temp2=edge[i].t;
 56             if(pre[temp2]==-1&&edge[i].f)
 57             {
 58                 pre[temp2]=pre[temp]+1;
 59                 q.push(temp2);
 60             }
 61         }
 62     }
 63     return pre[T]!=-1;
 64 }
 65 int dinic(int start,int last)
 66 {
 67     int flow=0,now;
 68     while(bfs(start,last))
 69     {
 70         int top=0;
 71         memcpy(cur,head,sizeof(head));
 72         int u=start;
 73         while(1)
 74         {
 75             if(u==last)//如果找到终点结束对中间路径进行处理并计算出该流
 76             {
 77                 int minn=INT_MAX;
 78                 for(int i=0; i<top; i++)
 79                 {
 80                     if(minn>edge[stack[i]].f)
 81                     {
 82                         minn=edge[stack[i]].f;
 83                         now=i;
 84                     }
 85                 }
 86                 for(int i=0;i<top;i++)
 87                 {
 88                     edge[stack[i]].f-=minn;
 89                     edge[stack[i]^1].f+=minn;
 90                 }
 91                 flow+=minn;
 92                 top=now;
 93                 u=edge[stack[top]].s;
 94             }
 95             for(int i=cur[u]; i!=-1; cur[u]=i=edge[i].next) //找出从u点出发能到的边
 96                 if(edge[i].f&&pre[edge[i].t]==pre[u]+1)
 97                     break;
 98             if(cur[u]==-1)//如果从该点未找到可行边,将该点标记并回溯
 99             {
100                 if(top==0)break;
101                 pre[u]=-1;
102                 u=edge[stack[--top]].s;
103             }
104             else//如果找到了继续运行
105             {
106                 stack[top++]=cur[u];
107                 u=edge[cur[u]].t;
108             }
109         }
110     }
111     return flow;
112 }
113 int main()
114 {
115     while(~scanf("%d%d",&n,&m))
116     {
117         int si,ni,ti;
118         int sum=0;
119         memset(head,-1,sizeof(head));
120         ent=0;
121         s=0;t=3*n+1;
122         int tot=0;
123         for(int i=1;i<=n;i++)
124         {
125             scanf("%d%d%d%d",&cust[i].start,&ni,&cust[i].last,&ti);
126             cust[i].stay=ni*ti;
127             sum+=cust[i].stay;
128             time[tot++]=cust[i].start;
129             time[tot++]=cust[i].last;
130         }
131         sort(time,time+2*n);
132         for(int i=1;i<=n;i++)
133             add(s,i,cust[i].stay);//cout<<"road:"<<i<<" start:"<<cust[i].start<<" last:"<<cust[i].last<<endl;}
134         //cout<<"time[0]:"<<time[0]<<endl;
135         for(int i=1;i<2*n;i++)
136         {
137             //cout<<"time["<<i<<"]:"<<time[i]<<endl;
138             if(time[i]==time[i-1])continue;
139             for(int j=1;j<=n;j++)
140             {
141                 if(cust[j].start<=time[i-1]&&cust[j].last>=time[i])
142                     add(j,n+i,m*(time[i]-time[i-1]));
143             }
144             add(n+i,t,m*(time[i]-time[i-1]));
145         }
146         //for(int i=0;i<ent;i++)
147             //if(edge[i].f)cout<<"s:"<<edge[i].s<<" t:"<<edge[i].t<<" f:"<<edge[i].f<<endl;
148         if(sum==dinic(s,t))
149             printf("Yes\n");
150         else printf("No\n");
151     }
152     return 0;
153 }
View Code

2.poj3469

题意:一台双核电脑,给你多个任务,分别给出每个任务在第一个核和第二个核上运行的消耗。后面的m行输入是给出两个任务在两个不同核上运行需要付出的额外消耗。

建图:把每个任务作为节点,在超级源点与任务间的连一条边,其容量为给任务在核1上运行的消耗,在该任务节点与超级汇点之间连一条边,容量为该任务在核2上运行的消耗。

           在任务之间连接无向边,容量为两个任务不在同一核上运行的额外消耗。

这题巧就巧在这句:在任务之间连接无向边,容量为两个任务不在同一核上运行的额外消耗。表示不是很理解,如果有大神在跪求带我装逼带我飞n(*≧▽≦*)n

代码:

技术分享
  1 #include<iostream>
  2 #include<queue>
  3 #include<cstring>
  4 #include<cstdio>
  5 #include<climits>
  6 #define MAXE 1641000
  7 #define MAXP 20010
  8 #define Max(a,b) a>b?a:b
  9 #define Min(a,b) a<b?a:b
 10 using namespace std;
 11 struct Edge
 12 {
 13     int s,t,f,next;
 14 } edge[MAXE];
 15 int head[MAXP];
 16 int cur[MAXP];
 17 int pre[MAXP];
 18 int stack[MAXE];
 19 int used[MAXP];
 20 int ent;
 21 int n,m,s,t;
 22 int num;
 23 void add(int start,int last,int f)
 24 {
 25     edge[ent].s=start;
 26     edge[ent].t=last;
 27     edge[ent].f=f;
 28     edge[ent].next=head[start];
 29     head[start]=ent++;
 30     edge[ent].s=last;
 31     edge[ent].t=start;
 32     edge[ent].f=0;
 33     edge[ent].next=head[last];
 34     head[last]=ent++;
 35 }
 36 bool bfs(int S,int T)
 37 {
 38     memset(pre,-1,sizeof(pre));
 39     pre[S]=0;
 40     queue<int>q;
 41     q.push(S);
 42     while(!q.empty())
 43     {
 44         int temp=q.front();
 45         q.pop();
 46         for(int i=head[temp]; i!=-1; i=edge[i].next)
 47         {
 48             int temp2=edge[i].t;
 49             if(pre[temp2]==-1&&edge[i].f)
 50             {
 51                 pre[temp2]=pre[temp]+1;
 52                 q.push(temp2);
 53             }
 54         }
 55     }
 56     return pre[T]!=-1;
 57 }
 58 int dinic(int start,int last)
 59 {
 60     int flow=0,now;
 61     while(bfs(start,last))
 62     {
 63         int top=0;
 64         memcpy(cur,head,sizeof(head));
 65         int u=start;
 66         while(1)
 67         {
 68             if(u==last)//如果找到终点结束对中间路径进行处理并计算出该流
 69             {
 70                 int minn=INT_MAX;
 71                 for(int i=0; i<top; i++)
 72                 {
 73                     if(minn>edge[stack[i]].f)
 74                     {
 75                         minn=edge[stack[i]].f;
 76                         now=i;
 77                     }
 78                 }
 79                 for(int i=0;i<top;i++)
 80                 {
 81                     edge[stack[i]].f-=minn;
 82                     edge[stack[i]^1].f+=minn;
 83                 }
 84                 flow+=minn;
 85                 top=now;
 86                 u=edge[stack[top]].s;
 87             }
 88             for(int i=cur[u]; i!=-1; cur[u]=i=edge[i].next) //找出从u点出发能到的边
 89                 if(edge[i].f&&pre[edge[i].t]==pre[u]+1)
 90                     break;
 91             if(cur[u]==-1)//如果从该点未找到可行边,将该点标记并回溯
 92             {
 93                 if(top==0)break;
 94                 pre[u]=-1;
 95                 u=edge[stack[--top]].s;
 96             }
 97             else//如果找到了继续运行
 98             {
 99                 stack[top++]=cur[u];
100                 u=edge[cur[u]].t;
101             }
102         }
103     }
104     return flow;
105 }
106 int main()
107 {
108     while(~scanf("%d%d",&n,&m))
109     {
110         memset(head,-1,sizeof(head));
111         ent=0;
112         s=0;t=n+1;
113         int cost1,cost2;
114         for(int i=1;i<=n;i++)
115         {
116             scanf("%d%d",&cost1,&cost2);
117             add(s,i,cost1);
118             add(i,t,cost2);
119         }
120         int u,v,cost;
121         for(int i=1;i<=m;i++)
122         {
123             scanf("%d%d%d",&u,&v,&cost);
124             add(u,v,cost);
125             add(v,u,cost);
126         }
127         printf("%d\n",dinic(s,t));
128     }
129     return 0;
130 }
View Code

 3.hdu3061

中文题,思路就是最大权闭合图(妈蛋我竟然一直没看出来,没活路了,不管什么算法不刷题果然都特么不行呀/(ㄒoㄒ)/~~)

代码:

技术分享
  1 #include<iostream>
  2 #include<algorithm>
  3 #include<queue>
  4 #include<cstring>
  5 #include<cstdio>
  6 #include<climits>
  7 #define MAXE 250000
  8 #define MAXP 500
  9 #define Max(a,b) a>b?a:b
 10 #define Min(a,b) a<b?a:b
 11 using namespace std;
 12 struct Edge
 13 {
 14     int s,t,f,next;
 15 } edge[MAXE];
 16 struct Cust
 17 {
 18     int start,last,stay;
 19 }cust[MAXP];
 20 int head[MAXP];
 21 int time[MAXP*2];
 22 int stay[MAXP];
 23 int cur[MAXP];
 24 int pre[MAXP];
 25 int stack[MAXE];
 26 int used[MAXP];
 27 int ent;
 28 int n,m,s,t;
 29 int num;
 30 void add(int start,int last,int f)
 31 {
 32     edge[ent].s=start;
 33     edge[ent].t=last;
 34     edge[ent].f=f;
 35     edge[ent].next=head[start];
 36     head[start]=ent++;
 37     edge[ent].s=last;
 38     edge[ent].t=start;
 39     edge[ent].f=0;
 40     edge[ent].next=head[last];
 41     head[last]=ent++;
 42 }
 43 bool bfs(int S,int T)
 44 {
 45     memset(pre,-1,sizeof(pre));
 46     pre[S]=0;
 47     queue<int>q;
 48     q.push(S);
 49     while(!q.empty())
 50     {
 51         int temp=q.front();
 52         q.pop();
 53         for(int i=head[temp]; i!=-1; i=edge[i].next)
 54         {
 55             int temp2=edge[i].t;
 56             if(pre[temp2]==-1&&edge[i].f)
 57             {
 58                 pre[temp2]=pre[temp]+1;
 59                 q.push(temp2);
 60             }
 61         }
 62     }
 63     return pre[T]!=-1;
 64 }
 65 int dinic(int start,int last)
 66 {
 67     int flow=0,now;
 68     while(bfs(start,last))
 69     {
 70         int top=0;
 71         memcpy(cur,head,sizeof(head));
 72         int u=start;
 73         while(1)
 74         {
 75             if(u==last)//如果找到终点结束对中间路径进行处理并计算出该流
 76             {
 77                 int minn=INT_MAX;
 78                 for(int i=0; i<top; i++)
 79                 {
 80                     if(minn>edge[stack[i]].f)
 81                     {
 82                         minn=edge[stack[i]].f;
 83                         now=i;
 84                     }
 85                 }
 86                 for(int i=0;i<top;i++)
 87                 {
 88                     edge[stack[i]].f-=minn;
 89                     edge[stack[i]^1].f+=minn;
 90                 }
 91                 flow+=minn;
 92                 top=now;
 93                 u=edge[stack[top]].s;
 94             }
 95             for(int i=cur[u]; i!=-1; cur[u]=i=edge[i].next) //找出从u点出发能到的边
 96                 if(edge[i].f&&pre[edge[i].t]==pre[u]+1)
 97                     break;
 98             if(cur[u]==-1)//如果从该点未找到可行边,将该点标记并回溯
 99             {
100                 if(top==0)break;
101                 pre[u]=-1;
102                 u=edge[stack[--top]].s;
103             }
104             else//如果找到了继续运行
105             {
106                 stack[top++]=cur[u];
107                 u=edge[cur[u]].t;
108             }
109         }
110     }
111     return flow;
112 }
113 int main()
114 {
115     while(~scanf("%d%d",&n,&m))
116     {
117         memset(head,-1,sizeof(head));
118         ent=0;s=0;t=n+1;
119         int cost,sum=0;
120         for(int i=1;i<=n;i++)
121         {
122             scanf("%d",&cost);
123             if(cost>0)
124             {
125                 add(s,i,cost);
126                 sum+=cost;
127             }
128             else
129                 add(i,t,-cost);
130         }
131         for(int i=1;i<=m;i++)
132         {
133             int u,v;
134             scanf("%d%d",&u,&v);
135             add(u,v,INT_MAX);
136         }
137         printf("%d\n",sum-dinic(s,t));
138     }
139     return 0;
140 }
View Code

 

网络流题目汇集(注:题意翻译以及思路基本都是摘录的别人的(虽然也许有的题目会是自己完全独立做出来的,但是题解一般都不会是自己的,人懒没办法))

标签:

原文地址:http://www.cnblogs.com/lthb/p/4504164.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!