题目大意:
给出一个无向图n个点,p条边,给一个数k,表示你可以把此图中任意的k条边的长度变成0.求出从1到n,经过的路径中最长的那一段路的长度的最小值!
思路:二分答案+缩点+BFS
二分最长的距离然后再剩余的图上缩点,再把那些删掉的边加到缩点后的图中,最后BFS判定最少的步数是否<=K;
PS:代码写的有点乱
源代码:
/*二分+缩点*/ /*AC代码:94ms*/ #include <iostream> #include <cstdio> #include <memory.h> #include <queue> #include <algorithm> #define MAXN 1005 #define INF 1e8 #define min(a,b) (a<b?a:b) #define max(a,b) (a>b?a:b) using namespace std; struct Node { int u,step; }; struct edge { int i,u,v,w,next; }E[5*10000],sE[5*10000],wE[5*10000]; int head[MAXN],ecnt; int shead[MAXN],secnt; int whead[MAXN],wecnt; int N,P,K,Max,Min; bool vis[MAXN]; int Belong[MAXN],scc; int len; void Insert(int u,int v,int w,edge E[],int &ecnt,int head[]) { E[ecnt].u=u; E[ecnt].v=v; E[ecnt].w=w; E[ecnt].next=head[u]; head[u]=ecnt++; } queue<Node>Q; void BFS(int s,int e) { int i,x; Node u,v; while(!Q.empty()) Q.pop(); memset(vis,false,sizeof(vis)); vis[s]=true; u.u=s;u.step=0; Q.push(u); while(!Q.empty()) { u=Q.front();Q.pop(); for(i=head[u.u];i!=-1;i=E[i].next) { x=E[i].v; if(!vis[x]) { vis[x]=true; v.u=x;v.step=u.step+1; if(x==e) {len=v.step;break;} Q.push(v); } } } } void Init() { int i,u,v,w; memset(head,-1,sizeof(head));ecnt=0; Max=0;Min=INF; for(i=1;i<=P;i++) { scanf("%d%d%d",&u,&v,&w); Max=max(Max,w); Min=min(Min,w); Insert(u,v,w,E,ecnt,head); Insert(v,u,w,E,ecnt,head); } } void dfs(int u,int id)//缩点 { int i,v; vis[u]=true; Belong[u]=id; for(i=shead[u];i!=-1;i=sE[i].next) { v=sE[i].v; if(!vis[v]) dfs(v,id); } } bool bfs(int s,int e)//对缩点后的图bfs { int i,x; Node u,v; while(!Q.empty()) Q.pop(); memset(vis,false,sizeof(vis)); vis[s]=true; u.u=s;u.step=0; Q.push(u); while(!Q.empty()) { u=Q.front();Q.pop(); if(u.step>K) return false; if(u.u==e) return true; for(i=whead[u.u];i!=-1;i=wE[i].next) { x=wE[i].v; if(!vis[x]) { vis[x]=true; v.u=x;v.step=u.step+1; Q.push(v); } } } return false; } bool Judge(int mid) { int i,u,v,w; memset(shead,-1,sizeof(shead));secnt=0; for(i=0;i<ecnt;i+=2) { u=E[i].u;v=E[i].v;w=E[i].w; if(E[i].w<=mid) { Insert(u,v,w,sE,secnt,shead); Insert(v,u,w,sE,secnt,shead); } } memset(vis,false,sizeof(vis)); scc=0; for(i=1;i<=N;i++) { if(!vis[i]) dfs(i,++scc); } if(Belong[1]==Belong[N]) return true; memset(whead,-1,sizeof(whead));wecnt=0; for(i=0;i<ecnt;i+=2) { u=E[i].u;v=E[i].v;w=E[i].w; if(w>mid&&Belong[u]!=Belong[v]) { Insert(Belong[u],Belong[v],w,wE,wecnt,whead); Insert(Belong[v],Belong[u],w,wE,wecnt,whead); } } return bfs(Belong[1],Belong[N]); } void Solve() { int l,r,mid; len=-1; BFS(1,N); if(len==-1) {printf("-1\n");return;} if(len<=K) {printf("0\n");return;} l=Min;r=Max; while(l!=r) { mid=(l+r)>>1; if(Judge(mid)) r=mid; else l=mid+1; } printf("%d\n",l); } int main() { while(scanf("%d%d%d",&N,&P,&K)!=EOF) { Init(); Solve(); } return 0; }