http://acm.cs.ecnu.edu.cn/problem.php?problemid=2104
题意:给出n个节点之间路径的载重量,求出从s点到t点的可行的最大载重量。
解法:n的数据量10^6,只能用邻接表存储,二分枚举最大载重量,用BFS遍历图判断是否合理,直到得到最优解。
1 #include<map> 2 #include<set> 3 #include<list> 4 #include<cmath> 5 #include<ctime> 6 #include<queue> 7 #include<stack> 8 #include<cctype> 9 #include<cstdio> 10 #include<string> 11 #include<vector> 12 #include<cstdlib> 13 #include<cstring> 14 #include<iostream> 15 #include<algorithm> 16 using namespace std; 17 const int maxn=1000005; 18 struct node{ 19 int v,w,next; 20 }edge[maxn]; //存储边邻接表 21 int head[maxn]; //头指针 22 int Q[maxn]; //BFS所用队列 23 bool mark[maxn]; //BFS用标记 24 int id,n; //边的编号,节点个数 25 void add(int u,int v,int w){ 26 edge[id].v=v; 27 edge[id].w=w; 28 edge[id].next=head[u]; 29 head[u]=id++; 30 } 31 bool bfs(int s,int t,int weight){ 32 memset(mark,0,sizeof(mark)); 33 int f=0,r=0; 34 Q[r++]=s; 35 mark[s]=1; 36 while(f<r){ 37 int tp=Q[f++]; 38 for(int i=head[tp];i!=-1;i=edge[i].next){ 39 int V=edge[i].v; 40 if(edge[i].w>=weight && mark[V]==0){ //将满足条件的顶点加入队 41 if(V==t)return true; //到达终点 42 mark[V]=1; 43 Q[r++]=V; 44 } 45 } 46 } 47 return false; 48 } 49 int main(){ 50 int m; 51 while(~scanf("%d%d",&n,&m)){ 52 int l=2000000001,r=0; 53 id=1; 54 memset(head,-1,sizeof(head)); 55 while(m--){ 56 int u,v,w; 57 scanf("%d%d%d",&u,&v,&w); 58 add(u,v,w); //双向边 59 add(v,u,w); 60 l=min(l,w); //记录最大上限与下限 61 r=max(r,w); 62 } 63 int s,t; 64 scanf("%d%d",&s,&t); 65 int ans; 66 while(l<=r){ //二分枚举载重 67 m=(l+r)/2; 68 if(bfs(s,t,m)){ ans=m;l=m+1;} 69 else r=m-1; 70 } 71 printf("%d ",ans); 72 } 73 return 0; 74 }
我再贴一个用stl写的
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cctype> 5 #include <vector> 6 #include <queue> 7 #include <algorithm> 8 using namespace std; 9 10 const int MAXN = 1000005; 11 12 int n, m, s, t; 13 int mark[MAXN]; 14 15 struct node 16 { 17 int v, w; 18 }; 19 20 vector<node>edge[MAXN]; 21 22 void add(int u, int v, int w) 23 { 24 node p; 25 p.v = v; 26 p.w = w; 27 edge[u].push_back(p); 28 } 29 30 bool bfs(int s, int t, int tmp) 31 { 32 memset(mark, 0, sizeof(mark)); 33 queue<int>q; 34 q.push(s); 35 mark[s] = 1; 36 while (!q.empty()) 37 { 38 int cur = q.front(); 39 q.pop(); 40 for (int i = 0; i < edge[cur].size(); i++) 41 { 42 int next = edge[cur][i].v; 43 int temp = edge[cur][i].w; 44 if (edge[cur][i].w >= tmp && mark[next] == 0) 45 { 46 if (next == t) return true; 47 mark[next] = 1; 48 q.push(next); 49 } 50 } 51 } 52 return false; 53 } 54 55 int main() 56 { 57 58 while (cin >> n >> m) 59 { 60 int l = 2000000001, r = 0; 61 for (int i = 0; i < MAXN; i++) 62 edge[i].clear(); 63 while (m--) 64 { 65 int u, v, w; 66 scanf("%d%d%d", &u, &v, &w); 67 add(u, v, w); 68 add(v, u, w); 69 l = min(w, l); 70 r = max(w, r); 71 } 72 cin >> s >> t; 73 int ans; 74 while (l <= r) 75 { 76 int tmp = (r + l + 1)/2; 77 if (bfs(s, t, tmp)) 78 { 79 l = tmp + 1; 80 ans = tmp; 81 } 82 else 83 r = tmp - 1; 84 } 85 printf("%d ", ans); 86 } 87 return 0; 88 }