4 4 1 2 2 2 3 4 1 4 1 3 4 2 2 1 3 1 2
1 0
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <string> #include <map> #include <stack> #include <vector> #include <set> #include <queue> #pragma comment (linker,"/STACK:102400000,102400000") #define maxn 205 #define MAXN 2005 #define mod 1000000009 #define INF 0x3f3f3f3f #define pi acos(-1.0) #define eps 1e-6 typedef long long ll; using namespace std; int n,m,ans,cnt,tot,flag; int a[2005],pp[205],q[205]; // pp-相当于邻接点的头指针 q-模拟队列 bool vis[205]; // 标记数组 int s,e,mi,ma,le,ri,mid; struct Node { int v,w,next; } edge[MAXN]; // 边 void addedge(int u,int v,int w) // 建图 { cnt++; edge[cnt].v=v; edge[cnt].w=w; edge[cnt].next=pp[u]; pp[u]=cnt; } bool bfs1() { int i,j,t,u,v,head=0,tail=-1; memset(vis,0,sizeof(vis)); // 标记数组清空 vis[s]=1; q[++tail]=s; // 起点进队列 while(head<=tail) // 当队中有元素 { u=q[head]; // 出队首 if(u==e) return true ; // 为e则能到达 head++; for(i=pp[u];i;i=edge[i].next) // 访问u的邻接点 { v=edge[i].v; if(!vis[v]&&edge[i].w>=mi) { vis[v]=1; if(v==e) return true ; // 为e则能到达 q[++tail]=v; } } } return false ; } bool bfs2() // 和bfs1基本一样 { int i,j,t,u,v,head=0,tail=-1; memset(vis,0,sizeof(vis)); vis[s]=1; q[++tail]=s; while(head<=tail) { u=q[head]; if(u==e) return true ; head++; for(i=pp[u];i;i=edge[i].next) { v=edge[i].v; if(!vis[v]&&edge[i].w>=mi&&edge[i].w<=a[mid]) { vis[v]=1; if(v==e) return true ; q[++tail]=v; } } } return false ; } void solve() { int i,j,t,q; scanf("%d",&q); sort(a+1,a+m+1); // 将边按照权值排序 while(q--) { scanf("%d%d",&s,&e); ans=INF; // 将答案出初始化为无穷大 for(i=1; i<=m; i++) // 枚举最小边 { mi=a[i]; if(!bfs1()) break ; // 看只走边>=最小边时s能否到达e 不能则后面的都不能到达了 退出循环 le=i; ri=m; while(le<ri) // 二分最大值所在的数组下标 { mid=(le+ri)>>1; if(bfs2()) ri=mid; // 看只走边在[a[le],a[ri]]范围内 s能否到达e else le=mid+1; } ans=min(ans,a[le]-mi); // 更新答案 } if(ans==INF) ans=-1; printf("%d\n",ans); } } int main() { int i,j,t; while(~scanf("%d%d",&n,&m)) { int u,v,w; cnt=0; memset(pp,0,sizeof(pp)); for(i=1; i<=m; i++) { scanf("%d%d%d",&u,&v,&w); addedge(u,v,w); // 建图 addedge(v,u,w); a[i]=w; // 记录权值 } solve(); } return 0; }
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <string> #include <map> #include <stack> #include <vector> #include <set> #include <queue> #pragma comment (linker,"/STACK:102400000,102400000") #define maxn 1005 #define MAXN 2005 #define mod 1000000009 #define INF 0x3f3f3f3f #define pi acos(-1.0) #define eps 1e-6 typedef long long ll; using namespace std; int n,m,ans,cnt,tot,flag; struct Node { int u,v,w; }edge[maxn]; int s,e; int pre[205]; bool cmp(Node xx,Node yy) // 排序用的比较函数 { return xx.w<yy.w; } int Find(int x) // 递归找到根节点 { if(x==pre[x]) return x; pre[x]=Find(pre[x]); return pre[x]; } void Merge(int x,int y) // 合并集合 { int u=Find(x),v=Find(y); if(u!=v) pre[u]=v; } void solve() { int i,j,t,q; scanf("%d",&q); sort(edge+1,edge+m+1,cmp); // 按照边权值排序 while(q--) { scanf("%d%d",&s,&e); ans=INF; for(i=1; i<=m; i++) // 枚举最小边 { for(j=1;j<=n;j++) pre[j]=j; // 并查集初始化 for(j=i;j<=m;j++) // 枚举最大边 { Merge(edge[j].u,edge[j].v); if(Find(s)==Find(e)) break ; } if(j<=m) // 能到达则更新ans { ans=min(ans,edge[j].w-edge[i].w); } } if(ans==INF) ans=-1; printf("%d\n",ans); } } int main() { int i,j,t; while(~scanf("%d%d",&n,&m)) { for(i=1; i<=m; i++) { scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w); } solve(); } return 0; }
hdu 1598 find the most comfortable road (二分+bfs 或者 并查集),布布扣,bubuko.com
hdu 1598 find the most comfortable road (二分+bfs 或者 并查集)
原文:http://blog.csdn.net/tobewhatyouwanttobe/article/details/20924347