题目大意:
给出一个无向图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;
}