Secret Milking Machine
来源:互联网 发布:盛世尊享年金保险 知乎 编辑:程序博客网 时间:2024/06/01 09:39
题意:给出一个图,从起点到终点,t条路径中最长边的最短是多少。
思路:最大流+二分。sap的模板。注意此题要用scanf与printf,否则会TLE滴。
#include<iostream>#include<string.h>#include<stdio.h>#define VM 4005#define INF 0x3f3f3f3fusing namespace std;int n,m;int s,sink;int head[VM],dep[VM],gap[VM];struct node{ int frm; int to; int cap; int next;}edge[999999];struct node1{ int u; int v; int c;}p[999999];int tot;int tmpn;void add(int u, int v, int c){ edge[tot].frm = u; edge[tot].to = v; edge[tot].cap = c; edge[tot].next = head[u]; head[u] = tot++; edge[tot].frm = v; edge[tot].to = u; edge[tot].cap = 0; edge[tot].next = head[v]; head[v] = tot++;}void BFS(int src, int des){ memset(dep, -1, sizeof(dep)); memset(gap, 0, sizeof(gap)); gap[0] = 1; //说明此时有1个dep[i] = 0 int Q[VM], front = 0, rear = 0; dep[des] = 0; Q[rear++] = des; int u, v; while (front != rear) { u = Q[front++]; front = front%VM; for (int i=head[u]; i!=-1; i=edge[i].next) { v = edge[i].to; if (edge[i].cap != 0 || dep[v] != -1) continue; Q[rear++] = v; rear = rear % VM; ++gap[dep[v] = dep[u] + 1]; //求出各层次的数量 } }}int SAP(int src, int des){ int res = 0; BFS(src, des); int cur[VM]; int S[VM], top = 0; memcpy(cur, head, sizeof(head)); int u = src, i; while (dep[src] < n) //n为结点的个数 { if (u == des) { int temp = INF, inser = n; for (i=0; i!=top; ++i) if (temp > edge[S[i]].cap) { temp = edge[S[i]].cap; inser = i; } for (i=0; i!=top; ++i) { edge[S[i]].cap -= temp; edge[S[i]^1].cap += temp; } res += temp; top = inser; u = edge[S[top]].frm; } if (u != des && gap[dep[u] -1] == 0)//出现断层,无增广路 break; for (i = cur[u]; i != -1; i = edge[i].next)//遍历与u相连的未遍历结点 if (edge[i].cap != 0 && dep[u] == dep[edge[i].to] + 1) //层序关系, 找到允许 break; if (i != -1)//找到允许弧 { cur[u] = i; S[top++] = i;//加入路径栈 u = edge[i].to;//查找下一个结点 } else //无允许的路径,修改标号当前点的标号比与之相连的点中最小的多1 { int min = n; for (i = head[u]; i != -1; i = edge[i].next) //找到与u相连的v中dep[v]最小的点 { if (edge[i].cap == 0) continue; if (min > dep[edge[i].to]) { min = dep[edge[i].to]; cur[u] = i; //最小标号就是最新的允许弧 } } --gap[dep[u]]; //dep[u] 的个数变化了 所以修改gap ++gap[dep[u] = min + 1]; //将dep[u]设为min(dep[v]) + 1, 同时修改相应的gap[] if (u != src) //该点非源点&&以u开始的允许弧不存在,退点 u = edge[S[--top]].frm; } } return res;}int isBuild(int mid,int tt){ memset(head,-1,sizeof(head)); tot=0; add(s,1,tt); for(int i=0;i<m;i++) { if(p[i].c<=mid)//小于中间流量的建边 { add(p[i].u,p[i].v,1); add(p[i].v,p[i].u,1); } } add(tmpn,sink,tt); if(SAP(s,sink)>=tt) return 1; return 0;}int main(){ int minc,maxc; int t; while(scanf("%d%d%d",&n,&m,&t)!=EOF) { minc=99999999; maxc=0; tmpn=n; s=0; sink=n+1; n+=2; for(int i=0;i<m;i++) { scanf("%d%d%d",&p[i].u,&p[i].v,&p[i].c); if(minc>p[i].c) minc=p[i].c; if(maxc<p[i].c) maxc=p[i].c; } int ans=0; while(minc<=maxc)//二分 { int mid=(maxc+minc)>>1; if(isBuild(mid,t)) { maxc=mid-1; ans=mid; } else minc=mid+1; } printf("%d\n",ans); } return 0;}
另一个sap模板,其实 差不多。
#include<iostream>#include<string.h>#include<stdio.h>#define VM 4005#define INF 0x3f3f3f3fusing namespace std;int n,m;int s,sink;int head[VM],dist[VM],gap[VM],cur[VM],pre[VM];struct node{ int to; int cap; int nxt;}edge[999999];struct node1{ int u; int v; int c;}p[999999];int ep;int tmpn;void add(int cu,int cv,int cw){ edge[ep].to = cv; edge[ep].cap = cw; edge[ep].nxt = head[cu]; head[cu] = ep; ep ++; edge[ep].to = cu; edge[ep].cap = 0; edge[ep].nxt = head[cv]; head[cv] = ep; ep ++;}int min (int a ,int b){ return a > b ? b : a;}int sap (int src,int des,int n){ memset (dist,0,sizeof(dist)); memset (gap,0,sizeof (dist)); memcpy (cur,head,sizeof(dist)); int res = 0; int u = pre[src] = src; int aug = INF; gap[0] = n; while (dist[src] < n) {loop: for (int &i = cur[u];i != -1;i = edge[i].nxt) { int v = edge[i].to; if (edge[i].cap && dist[u] == dist[v] + 1) { aug = min (aug,edge[i].cap); pre[v] = u; u = v; if (v == des) { res += aug; for (u = pre[u];v != src;v = u,u = pre[u]) { edge[cur[u]].cap -= aug; edge[cur[u]^1].cap += aug; } aug = INF; // } goto loop; } } int mindist = n; // for (int i = head[u];i != -1;i = edge[i].nxt) { int v = edge[i].to; if (edge[i].cap && mindist > dist[v]) { cur[u] = i; mindist = dist[v]; } } if ((--gap[dist[u]]) == 0) break; dist[u] = mindist + 1; gap[dist[u]] ++; u = pre[u]; } return res;}int isBuild(int mid,int tt){ memset(head,-1,sizeof(head)); ep=0; add(s,1,tt); for(int i=0;i<m;i++) { if(p[i].c<=mid) { add(p[i].u,p[i].v,1); add(p[i].v,p[i].u,1); } } add(tmpn,sink,tt); if(sap(s,sink,n)>=tt) return 1; return 0;}int main(){ int minc,maxc; int t; while(scanf("%d%d%d",&n,&m,&t)!=EOF) { minc=99999999; maxc=0; tmpn=n; s=0; sink=n+1; n+=2; for(int i=0;i<m;i++) { scanf("%d%d%d",&p[i].u,&p[i].v,&p[i].c); if(minc>p[i].c) minc=p[i].c; if(maxc<p[i].c) maxc=p[i].c; } int ans=0; while(minc<=maxc) { int mid=(maxc+minc)>>1; if(isBuild(mid,t)) { maxc=mid-1; ans=mid; } else minc=mid+1; } printf("%d\n",ans); } return 0;}
- poj Secret Milking Machine
- Secret Milking Machine
- POJ2455 Secret Milking Machine
- POJ2455-Secret Milking Machine
- Secret Milking Machine POJ
- POJ 2455 Secret Milking Machine
- poj 2455 Secret Milking Machine
- poj 2455 Secret Milking Machine
- POJ-2455-Secret Milking Machine
- POJ 2455 Secret Milking Machine
- poj 2455 Secret Milking Machine
- 2455 Secret Milking Machine //二分答案+SAP
- POJ 2455 Secret Milking Machine (最大流)
- 最大流+二分Secret Milking Machine
- POJ Secret Milking Machine 【网络流+二分】
- 【网络流】 POJ 2455 Secret Milking Machine
- 解题报告 之 POJ2455 Secret Milking Machine
- POJ 2455.Secret Milking Machine【最大流+二分】
- 四级核心词汇表<二>
- 面试题——嵌入式软件开发(1)
- 浙大oj 1294 golf
- 四级核心词汇表<三>
- 四级核心词汇表<四>
- Secret Milking Machine
- 我的第一个java窗口
- 四级核心词汇表<五>
- 浙大oj 1221 Risk
- 四级核心词汇表<六>
- C中程序的内存分配
- Core Data 自动生成及基本数据操作(1)
- 什么是牛人
- 2012-10-18 11gR2 concepts page 326 - 367