http://acm.hdu.edu.cn/showproblem.php?pid=1598
中文题:找到一条s到t的路,其中边的差值最小,输出这个差值,如果不存在输出-1。
枚举差值,先将边保存起来,获得最大最小边权差值(二分的上界下界)。枚举一个差值,将符合差值的边加入图中,跑bfs,看从s是否能够到达t,我这儿输出-1的处理是给上界是加了个1,如果最后答案出界了,说明不存在s到t的路线。也是失了智,把m写错n,一直在re(╥╯^╰╥)
#include<cstdio> #include<cstring> #include<queue> #include<vector> #include<algorithm> using namespace std; const int INF = 1<<30; struct node { int u,d; bool operator < (const node &b)const { return d>b.d; } }; struct edge { int v,w,next; } e[2*1010]; struct E { int u,v,w; }; vector<E> v; int head[210],vis[210]; int tot; bool cmp(E a,E b) { return a.w<b.w; } void addedge(int u,int v,int w) { e[tot].v=v; e[tot].w=w; e[tot].next=head[u]; head[u]=tot++; } bool bfs(int s,int t) { queue<int> q; memset(vis,0,sizeof(vis)); q.push(s); vis[s]=1; while(!q.empty()) { int u=q.front(); q.pop(); if(u==t)return true; for(int i=head[u]; i!=-1; i=e[i].next) { int v=e[i].v; if(!vis[v]) { vis[v]=1; q.push(v); } } } return false; } void init() { memset(head,-1,sizeof(head)); tot=0; } bool check(int s,int t,int mid) { for(int i=0; i<v.size(); i++) { int low=v[i].w; init(); for(int j=i; j<v.size(); j++) { if(v[j].w-low>mid)break; addedge(v[j].u,v[j].v,1); addedge(v[j].v,v[j].u,1); } if(bfs(s,t)) { return 1; } } return 0; } int main() { int n,m; while(~scanf("%d%d",&n,&m)) { v.clear(); init(); for(int i=0; i<m; i++) { int u,V,w; scanf("%d%d%d",&u,&V,&w); v.push_back(E{u,V,w}); } sort(v.begin(),v.end(),cmp); int RL=v[v.size()-1].w-v[0].w; int LL=INF; for(int i=1; i<v.size(); i++) LL=min(LL,v[i].w-v[i-1].w); int q; scanf("%d",&q); while(q--) { int s,t; scanf("%d%d",&s,&t); int l=LL,r=RL+1; while(l<r) { int mid=(l+r)>>1; if(check(s,t,mid)) r=mid; else l=mid+1; } if(l==RL+1) printf("-1\n"); else printf("%d\n",l); } } }和UVA1395类似的做法,uva这道题是求最小生成树中最大最小边权差值最小。这里只要s和t连通就可以判断了。
#include<cstdio> #include<algorithm> using namespace std; const int maxn = 110; int f[maxn]; struct edge { int from,to,w; } e[maxn*maxn+20]; bool cmp(edge a,edge b) { return a.w<b.w; } int Find(int x) { return f[x]==x?x:f[x]=Find(f[x]); } int main() { int n,m; //n=[2,100] // freopen("in.txt","r",stdin); while(~scanf("%d%d",&n,&m)&&(m+n)) { int i=0; for(i=0; i<m; i++) scanf("%d%d%d",&e[i].from,&e[i].to,&e[i].w); sort(e,e+m,cmp); int q; scanf("%d",&q); while(q--) { int s,t; scanf("%d%d",&s,&t); int ans=1<<30; for(i=0; i<m; i++) { for(int k=1; k<=n; k++)f[k]=k; int j=i; for(; j<m; j++) { int u=e[j].from,v=e[j].to; int xx=Find(u); int yy=Find(v); if(xx!=yy) { f[xx]=yy; } if(Find(s)==Find(t)) { if(ans>(e[j].w-e[i].w)) { ans=(e[j].w-e[i].w); } break; } } } if(ans!=1<<30) printf("%d\n",ans); else printf("-1\n"); } } }