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

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

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

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 }

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 }

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 }

时间: 2024-08-05 12:23:19

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

程序员新人如何在企业与人打好交道 站在别人的立场想问题,站在自己的立场做事情

http://www.nowamagic.net/librarys/veda/detail/1118 尽量记住别人的名字,尊重他人 新人刚进公司,往往会有人带着去见识熟悉一下同事,嗯,这是常规的走过场了.往往新人们也觉得这是走过场,那么多人怎么能记得住,反正以后日子长了就会记得了,就不放在心上.其实这是不可忽略的.我们自己也试过,如果和某君见过一面,他在第二次见面能叫上你名字,这是什么感觉?是一种被别人重视,被别人尊重的感觉,往往你也很容易和这样的人成为好友.有人说我记性不好,总记不起别人名字,

沃顿统计社11月的题目(附中文翻译)

To decide who would play first in a human vs. AI chess match, the human contender, Garry, suggested flipping a coin. 为了决定谁在人机象棋比赛里有先走权,嘉里说,抛硬币决定.He produced a quarter from his pocket, stating heads you win, tails I win. 他从裤子里掏出一枚硬币,说正面你赢,反面我赢.The com

题目1134:密码翻译

题目描述: 在情报传递过程中,为了防止情报被截获,往往需要对情报用一定的方式加密,简单的加密算法虽然不足以完全避免情报被破译,但仍然能防止情报被轻易的识别.我们给出一种最简的的加密方法,对给定的一个字符串,把其中从a-y,A-Y的字母用其后继字母替代,把z和Z用a和A替代,则可得到一个简单的加密字符串. 输入: 可能有多组测试数据.每组测试数据的第一行是字符串的数目n, (也要使用get(s)读取字符串,再用n=atoi(s)获得整数数值),其余n行每行一个字符串,用gets(s)方式读取这一行

爆气球这道题目,展开了新的思路

https://leetcode.com/problems/burst-balloons/?tab=Description https://discuss.leetcode.com/topic/30746/share-some-analysis-and-explanations/2 它的方式,是采用最后爆破的,作为分隔点.那么就可以用DP了.又因为始终有一前一后两个坐标,而这两个坐标,是不变的,所以便于写代码.

基于网络流音视频包的音视频解码思路

本篇文章对自己项目中的网络媒体流解码流程进行了梳理和总结.本文中的方法不同于一般打开文件或流进行读写的流程,不需要通过avformat_open_input,avformat_find_stream_info等操作获取AVFormatContext,然后遍历不同流信息.此处直接通过解析音视频sequence header包,获取相应的参数来初始化对应的AVCodec和AVCodecContext,然后使用AVCodecContext进行后续的解码操作.由于项目中直接获取到了音视频包,所以也省去了

这些年,我身边的那些人和事

引言 2013年的8月13日,群主打开自己的QQ,建立了第一个技术交流群,也就是现在的交流一群. 时光飞逝,转眼之间,3年半已经过去了. 当初建群的时候,群主才工作不到两年,期间借着业余时间,写了一个设计模式的系列,因此吸引了一批同道中人一起学习.为了给大家一个一起交流的地方,群主便顺手建了一个QQ群. 谁曾想,3年半过去了,这个无意之中建立的QQ群,不止见证了群主的成长,也见证了群里小伙伴儿的成长. 今天这篇文章,群主就和大家一起说说,群里的那些人和事. 这些过往的人和事,或许会让你产生共鸣,

大前端开发者需要了解的基础编译原理和语言知识

转自:https://yq.aliyun.com/articles/180879 在我刚刚进入大学,从零开始学习 C 语言的时候,我就不断的从学长的口中听到一个又一个语言,比如 C++.Java.Python.JavaScript 这些大众的,也有 Lisp.Perl.Ruby 这些相对小众的.一般来说,当程序员讨论一门语言的时候,默认的上下文经常是:“用 xxx 语言来完成 xxx 任务”.所以一直困扰着的我的一个问题就是,为什么完成某个任务,一定要选择特定的语言,比如安卓开发是 Java,前

4/13 收获满意offer!

今天是来到北京第二天.之前一直在想,到底什么样的offer能让我满意,或者我想要的工作是什么样的,但都没有一个大概的轮廓. 昨天下午.今天上午.今天下午,来了一天半,面了三场,各有感觉.第一场地理位置很靠前,在朝阳门附近,足证公司实力,进入公司,感觉到每个人都很严谨地工作,前台接待态度也非常好,一直到做笔试题之前,感觉都非常良好,但是因为笔试题的原因,我被PASS掉了,当然,我更愿意认为是其对算法的不理解导致我将其PASS掉的,也算是给自己一点心理安慰,后来也发现确实语法部分有所欠缺,在此不再赘

noip2010-t3

[题目描述] S 城现有两座监狱,一共关押着N 名罪犯,编号分别为1~N.他们之间的关系自然也极不和谐.很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突.我们用“怨气值”(一个正整数值)来表示某两名罪犯之间的仇恨程度,怨气值越大,则这两名罪犯之间的积怨越多.如果两名怨气值为c 的罪犯被关押在同一监狱,他们俩之间会发生摩擦,并造成影响力为c 的冲突事件.每年年末,警察局会将本年内监狱中的所有冲突事件按影响力从大到小排成一个列表,然后上报到S 城Z 市长那里.公务繁忙的Z 市长只会去看列