最短路+最大流
思维难度并不高,其实题面几乎已经把算法讲完了……
练习模板的好题= =
哦对了,求最短路和最大流的时候都得开long long……QwQ
1 /************************************************************** 2 Problem: 3931 3 User: Tunix 4 Language: C++ 5 Result: Accepted 6 Time:316 ms 7 Memory:12256 kb 8 ****************************************************************/ 9 10 //BZOJ 3931 11 #include<vector> 12 #include<queue> 13 #include<cstdio> 14 #include<cstring> 15 #include<cstdlib> 16 #include<iostream> 17 #include<algorithm> 18 #define rep(i,n) for(int i=0;i<n;++i) 19 #define F(i,j,n) for(int i=j;i<=n;++i) 20 #define D(i,j,n) for(int i=j;i>=n;--i) 21 #define pb push_back 22 using namespace std; 23 typedef long long LL; 24 inline int getint(){ 25 int v=0,sign=1; char ch=getchar(); 26 while(ch<‘0‘||ch>‘9‘){ if (ch==‘-‘) sign=-1; ch=getchar();} 27 while(ch>=‘0‘&&ch<=‘9‘){ v=v*10+ch-‘0‘; ch=getchar();} 28 return v*sign; 29 } 30 const int N=1010,M=200010; 31 const LL INF=1e15; 32 /******************tamplate*********************/ 33 34 int head[N],to[M<<1],nxt[M<<1],l[M<<1],cnt; 35 typedef long long LL; 36 void add(int x,int y,int z){ 37 to[++cnt]=y; nxt[cnt]=head[x]; head[x]=cnt; l[cnt]=z; 38 to[++cnt]=x; nxt[cnt]=head[y]; head[y]=cnt; l[cnt]=z; 39 } 40 int n,m,a[N],vis[N],tot; 41 LL ans,dis[N],c[N]; 42 43 void Dij(); 44 struct edge{int to;LL v;}; 45 struct Net{ 46 edge E[M<<1]; 47 int head[N],nxt[M<<1],cnt; 48 void ins(int x,int y,LL z){ 49 E[++cnt]=(edge){y,z}; nxt[cnt]=head[x]; head[x]=cnt; 50 } 51 void add(int x,int y,LL z){ 52 ins(x,y,z); ins(y,x,0); 53 } 54 int S,T,d[N],cur[N]; 55 queue<int>Q; 56 bool mklevel(){ 57 memset(d,-1,sizeof d); 58 d[S]=0; 59 Q.push(S); 60 while(!Q.empty()){ 61 int x=Q.front(); Q.pop(); 62 for(int i=head[x];i;i=nxt[i]) 63 if (d[E[i].to]==-1 && E[i].v){ 64 d[E[i].to]=d[x]+1; 65 Q.push(E[i].to); 66 } 67 } 68 return d[T]!=-1; 69 } 70 int dfs(int x,LL a){ 71 if (x==T) return a; 72 LL flow=0; 73 for(int &i=cur[x];i && flow<a;i=nxt[i]) 74 if (d[E[i].to]==d[x]+1 && E[i].v){ 75 LL f=dfs(E[i].to,min(E[i].v,a-flow)); 76 E[i].v-=f; 77 E[i^1].v+=f; 78 flow+=f; 79 } 80 if (!flow) d[x]=-1; 81 return flow; 82 } 83 void Dinic(){ 84 while(mklevel()){ 85 F(i,0,T) cur[i]=head[i]; 86 ans+=dfs(S,INF); 87 } 88 } 89 void init(){ 90 S=0,T=n*2+1; cnt=1; 91 Dij(); 92 F(i,1,n) add(i,n+i,c[i]); 93 add(S,1,INF); add(n+n,T,INF); 94 Dinic(); 95 printf("%lld\n",ans); 96 } 97 }G1; 98 typedef pair<int,int> pii; 99 #define mp make_pair 100 #define fi first 101 #define se second 102 103 priority_queue<pii,vector<pii>,greater<pii> >Q; 104 void Dij(){ 105 memset(dis,0x3f,sizeof dis); 106 dis[1]=0; 107 Q.push(mp(0,1)); 108 while(!Q.empty()){ 109 int x=Q.top().se; Q.pop(); 110 if (vis[x]) continue; 111 vis[x]=++tot; 112 a[tot]=x; 113 for(int i=head[x];i;i=nxt[i]) 114 if (dis[to[i]]>dis[x]+l[i]){ 115 dis[to[i]]=dis[x]+l[i]; 116 Q.push(mp(dis[to[i]],to[i])); 117 } 118 } 119 F(x,1,n) 120 for(int i=head[x];i;i=nxt[i]) 121 if (dis[to[i]]==dis[x]+l[i]) 122 G1.add(x+n,to[i],INF); 123 } 124 int main(){ 125 #ifndef ONLINE_JUDGE 126 freopen("3931.in","r",stdin); 127 freopen("3931.out","w",stdout); 128 #endif 129 n=getint(); m=getint(); 130 F(i,1,m){ 131 int x=getint(),y=getint(),z=getint(); 132 add(x,y,z); 133 } 134 F(i,1,n) c[i]=getint(); 135 c[1]=c[n]=INF; 136 G1.init(); 137 return 0; 138 }
3931: [CQOI2015]网络吞吐量
Time Limit: 10 Sec Memory Limit: 512 MB
Submit: 653 Solved: 287
[Submit][Status][Discuss]
Description
路
由是指通过计算机网络把信息从源地址传输到目的地址的活动,也是计算机网络设计中的重点和难点。网络中实现路由转发的硬件设备称为路由器。为了使数据包最
快的到达目的地,路由器需要选择最优的路径转发数据包。例如在常用的路由算法OSPF(开放式最短路径优先)中,路由器会使用经典的Dijkstra算法
计算最短路径,然后尽量沿最短路径转发数据包。现在,若已知一个计算机网络中各路由器间的连接情况,以及各个路由器的最大吞吐量(即每秒能转发的数据包数
量),假设所有数据包一定沿最短路径转发,试计算从路由器1到路由器n的网络的最大吞吐量。计算中忽略转发及传输的时间开销,不考虑链路的带宽限制,即认
为数据包可以瞬间通过网络。路由器1到路由器n作为起点和终点,自身的吞吐量不用考虑,网络上也不存在将1和n直接相连的链路。
Input
输入文件第一行包含两个空格分开的正
整数n和m,分别表示路由器数量和链路的数量。网络中的路由器使用1到n编号。接下来m行,每行包含三个空格分开的正整数a、b和d,表示从路由器a到路
由器b存在一条距离为d的双向链路。 接下来n行,每行包含一个正整数c,分别给出每一个路由器的吞吐量。
Output
输出一个整数,为题目所求吞吐量。
Sample Input
7 10
1 2 2
1 5 2
2 4 1
2 3 3
3 7 1
4 5 4
4 3 1
4 6 1
5 6 2
6 7 1
1
100
20
50
20
60
1
Sample Output
70
HINT
对于100%的数据,n≤500,m≤100000,d,c≤10^9