hdu 3986

题目要求删除图上的一条边,使得最短路最长,也可以删边后不可达。

先跑一遍最短路,求出不删边时最短路上的所有边。然后枚举删除这些边,再次迪杰斯特拉,每次更新最大值。

作为一个菜鸡,这题一A了,然后没出息的笑了笑。

上代码

#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
#include<algorithm>
using namespace std;
const int maxn = 1005;
const int inf = 1<<20;
int n,m;
struct node{
	int to;
	int next;
	int w;
	int vis;
	node(){
	}
	node(int a,int b,int c):to(a),next(b),w(c){
		vis = 0;
	}
}edge[50002<<1];
int head[maxn];
int tot;
void add_edge(int u,int v,int w)
{
	edge[tot] = node(v,head[u],w);
	head[u] = tot++;
	edge[tot] = node(u,head[v],w);
	head[v] = tot++;
}
int dist[maxn];
struct Edge{
	int id;
	int dist;
	Edge(int a,int b):id(a),dist(b){
	}
	bool operator < (const Edge& T)const{
		return dist>T.dist;
	}
};
int par[maxn];
int cost[maxn];
vector<int>G[maxn];
void dij()
{
	for(int i=1;i<=n;i++){
		par[i] = i; 
		dist[i] = inf;
	}
	priority_queue<Edge>que;
	dist[1] = 0;
	que.push(Edge(1,0));
	while(!que.empty())
	{
		Edge edg = que.top(); que.pop();
		if(dist[edg.id]<edg.dist) continue;
		for(int i=head[edg.id];i!=-1;i=edge[i].next)
		{
			if(edge[i].vis==2) continue;
			int v = edge[i].to;
			int w = edge[i].w;
			if(dist[v]>dist[edg.id]+w)
			{
				dist[v] = dist[edg.id]+w;
				par[v] = edg.id;
				cost[v] = w;
				que.push(Edge(v,dist[v]));
			}
		}
	}
}
int main()
{
	int cases;
	scanf("%d",&cases);
	while(cases--)
	{
		int u,v,w;
		scanf("%d%d",&n,&m);
		tot = 0;
		memset(head,-1,sizeof(head));
		for(int i=0;i<m;i++)
		{
			scanf("%d%d%d",&u,&v,&w);
			add_edge(u,v,w);
		}
		for(int i=1;i<=n;i++)
		G[i].clear();
		dij();
		if(dist[n]==inf)
		{
			printf("-1\n");
			continue;
		}
		int k = n;
		while(k!=par[k])
		{
		//	printf("%d\n",k);
			G[par[k]].push_back(k);
			k = par[k];
		}
		int ma = -1;
		for(int i=1;i<=n;i++)
		{
			if((int)G[i].size()==0)
			continue;
			int x = i;
			int y = G[i][0];
			int cc = cost[y];
			int temp;
			for(int j=head[x];j!=-1;j=edge[j].next)
			{
				int to = edge[j].to;
				int w = edge[j].w;
				if(to==y&&w==cc)
				{
					edge[j].vis = 2;
					temp = j;
				//	printf("%d\n",j);
					break;
				}
			}
			dij();
		//	printf("%d\n",dist[n]);
			edge[temp].vis = 0;
			ma = max(ma,dist[n]);
		}
		if(ma==inf)
		printf("-1\n");
		else
		printf("%d\n",ma);
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值