题目大意:给定一张无向图,求拆去任意一边后由1至N最短路的最大值。
在程序中:存图时采用邻接表。利用堆优化dijkstra算法多次求最短路,第一次设置flag为true将路径上的点记录于pre[ ]数组中,再利用过程getpath( )求出相关点。在删边时,将边上的两点u,v的数组arrive[ ]值均置为false,求最短路时若某边的两点i,j的arrive[ ]值均为false则跳过,过后恢复。最后对ans与dis[n]求最大值。
- 程序如下:
#include<iostream>
#include<cstdio>
#include<vector>
#include<queue>
#include<cstring>
using namespace std;
struct edge
{
int to,cost;
edge(int to=0,int cost=0):to(to),cost(cost){}
};
struct node
{
int id,len;
node(int id=0,int len=0):id(id),len(len){}
bool operator <(const node &a) const
{
return len>a.len;
}
};
const int maxn=1005;
const int oo=100000;
int n,m,pre[maxn],ans=0;
vector<edge> g[maxn];
bool arrive[maxn];
void init()
{
memset(pre,-1,sizeof(pre));
memset(arrive,1,sizeof(arrive));
int a,b,v;
scanf("%d%d",&n,&m);
for (int i=1;i<=m;++i)
{
scanf("%d%d%d",&a,&b,&v);
g[a].push_back(edge(b,v));
g[b].push_back(edge(a,v));
}
}
int dis[maxn];
bool vis[maxn];
int dijkstra(bool flag)
{
int i,j,k;
priority_queue<node> q;
memset(vis,0,sizeof(vis));
for (i=1;i<=n;++i)
dis[i]=oo;
dis[1]=0;
q.push(node(1,0));
for (i=1;i<=n;++i)
{
while (q.size() && vis[q.top().id])
q.pop();
if (q.empty())
break;
int x=q.top().id;
q.pop();
vis[x]=1;
vector<edge>::iterator it;
for (it=g[x].begin();it!=g[x].end();++it)
{
if ( (arrive[(*it).to] || arrive[x]) && !vis[(*it).to] && dis[(*it).to]>dis[x]+(*it).cost)
{
dis[(*it).to]=dis[x]+(*it).cost;
if (flag)
{
pre[(*it).to]=x;
}
q.push(node((*it).to,dis[(*it).to]));
}
}
}
}
int path[maxn],cnt=1;
void getpath()
{
int p=path[1]=n;
while (pre[p]!=1)
{
p=pre[p];
path[++cnt]=p;
}
path[++cnt]=1;
}
int main()
{
init();
dijkstra(true);
getpath();
for (int j=1;j<=cnt-1;++j)
{
arrive[path[j]]=false;
arrive[path[j+1]]=false;
dijkstra(false);
if (dis[n]>ans)
ans=dis[n];
arrive[path[j]]=true;
arrive[path[j+1]]=true;
}
printf("%d",ans);
return 0;
}