hdu1595

题意

删除1—N最短路上的一条边,使图剩下部分1—N的最短路最长  

关于多条最短路:

这道题目的思路还是很容易想到的,我们直接找最短路,然后枚举删除最短路上的边,然后找出结果就行了。但值得一提的是,开始自己考虑了有多条最短路的问题,然后我就将所有最短路上的边都进行标记,然后就MLE了,感觉出题不严谨。其实不是,就算有多条最短路,我们只需要其中一条就行了。

多条最短路有两种情况

  1. 最短路没有重合边:这个时候我们删除任意其中一条最短路上的边,求出的最短路还是不变的。
  2. 两条最短路有重合边,这个时候我们只要删除一条重合边,就能让图不连通。
  3. 多条最短路头重合边,可以分别转化成1、2的情况

 只找出一条最短路就可以,AC代码

#include <bits/stdc++.h> 
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define res register int 
const int maxn=1005;
int N,M;
int dis[maxn][maxn];
int pre[maxn];

int dij1()
{
	int len[maxn],vis[maxn];
	memset(vis,0,sizeof(vis));
	memset(len,inf,sizeof(len));
	len[1]=0;
	for(res i=2;i<=N;i++){
		len[i]=dis[1][i];
		if(inf!=dis[1][i]) pre[i]=1;
	}
	vis[1]=1;
	for(res i=1;i<=N-1;i++){
		int minc=inf,p=-1;
		for(res j=1;j<=N;j++){
			if(!vis[j]&&len[j]<minc){
				minc=len[j];
				p=j;
			}
		}
		if(inf==minc) break;
		vis[p]=1;
		for(res j=1;j<=N;j++){
			if(!vis[j]&&len[j]>len[p]+dis[p][j]){
				len[j]=len[p]+dis[p][j];
				pre[j]=p;
			}
		}
	}
	if(inf==len[N]) return -1;
	else return len[N];
}

int dij2()
{
	int len[maxn],vis[maxn];
	memset(vis,0,sizeof(vis));
	memset(len,inf,sizeof(len));
	len[1]=0;
	for(res i=2;i<=N;i++){
		len[i]=dis[1][i];
	}
	vis[1]=1;
	for(res i=1;i<=N-1;i++){
		int minc=inf,p=-1;
		for(res j=1;j<=N;j++){
			if(!vis[j]&&len[j]<minc){
				minc=len[j];
				p=j;
			}
		}
		if(inf==minc) break;
		vis[p]=1;
		for(res j=1;j<=N;j++){
			if(!vis[j]&&len[j]>len[p]+dis[p][j])
				len[j]=len[p]+dis[p][j];
		}
	}
	if(inf==len[N]) return -1;
	else return len[N];
}

int main()
{
	while(EOF!=scanf("%d%d",&N,&M))
	{
		//init
		for(res i=0;i<=N;i++){
			for(res j=0;j<=N;j++){
				dis[i][j]=inf;
			}
			dis[i][i]=0;
			pre[i]=-1;
		} 
		 
		int from,to,val;
		for(res i=0;i<M;i++){
			scanf("%d%d%d",&from,&to,&val);
			dis[from][to]=dis[to][from]=val; 
		}		
		int ans=dij1();
		if(-1==ans){
			printf("-1\n");
			continue;
		}
		//开始枚举每一条边
//		for(res i=1;i<=N;i++){
//			printf("%d:",i); 
//			for(res j=0;j<pre[i].size();j++){
//				printf("%d ",pre[i][j]);
//			} 
//			printf("\n");
//		}
		ans=-inf;
		int flag=0;
		int t=N;
		while(-1!=pre[t]){
			int to=t,from=pre[t];
			int temp1=dis[from][to],temp2;
			dis[from][to]=dis[to][from]=inf;
			temp2=dij2();
			if(-1==temp2){
				ans=-1;
				flag=1;
				break;
			} 
			ans=max(ans,temp2);
			dis[from][to]=dis[to][from]=temp1;
			t=pre[t];	
		}
		printf("%d\n",ans);
	}
}

记录所有最短路上的边就MLE

#include <bits/stdc++.h> 
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define res register int 
const int maxn=1005;
int N,M;
int dis[maxn][maxn];
vector<int> pre[maxn];
vector<int> e[maxn];

int dij1()
{
	int len[maxn],vis[maxn];
	memset(vis,0,sizeof(vis));
	memset(len,inf,sizeof(len));
	len[1]=0;
	for(res i=2;i<=N;i++){
		len[i]=dis[1][i];
		if(inf!=dis[1][i]) pre[i].push_back(1);
	}
	vis[1]=1;
	for(res i=1;i<=N-1;i++){
		int minc=inf,p=-1;
		for(res j=1;j<=N;j++){
			if(!vis[j]&&len[j]<minc){
				minc=len[j];
				p=j;
			}
		}
		if(inf==minc) break;
		vis[p]=1;
		for(res j=1;j<=N;j++){
			if(!vis[j]&&len[j]>len[p]+dis[p][j]){
				len[j]=len[p]+dis[p][j];
				pre[j].clear();
				pre[j].push_back(p);
//				e[p].clear();
//				e[p].push_back((edge){j,dis[p][j]});
			}else if(!vis[j]&&len[j]==len[p]+dis[p][i]){
				pre[j].push_back(p); 
//				e[p].push_back((edge){j,dis[p][j]});
			}
		}
	}
	if(inf==len[N]) return -1;
	else return len[N];
}

int dij2()
{
	int len[maxn],vis[maxn];
	memset(vis,0,sizeof(vis));
	memset(len,inf,sizeof(len));
	len[1]=0;
	for(res i=2;i<=N;i++){
		len[i]=dis[1][i];
	}
	vis[1]=1;
	for(res i=1;i<=N-1;i++){
		int minc=inf,p=-1;
		for(res j=1;j<=N;j++){
			if(!vis[j]&&len[j]<minc){
				minc=len[j];
				p=j;
			}
		}
		if(inf==minc) break;
		vis[p]=1;
		for(res j=1;j<=N;j++){
			if(!vis[j]&&len[j]>len[p]+dis[p][j])
				len[j]=len[p]+dis[p][j];
		}
	}
	if(inf==len[N]) return -1;
	else return len[N];
}

void dfs(int n)
{
	if(1==n) return;
	int fa;
	for(res i=0;i<pre[n].size();i++){
		fa=pre[n][i];
		dfs(fa);
		e[fa].push_back(n);
	}
}

int main()
{
	while(EOF!=scanf("%d%d",&N,&M))
	{
		//init
		for(res i=0;i<=N;i++){
			e[i].clear();			
			for(res j=0;j<=N;j++){
				dis[i][j]=inf;
			}
			dis[i][i]=0;
		} 
		 
		int from,to,val;
		for(res i=0;i<M;i++){
			scanf("%d%d%d",&from,&to,&val);
			dis[from][to]=dis[to][from]=val; 
		}		
		int ans=dij1();
		if(-1==ans){
			printf("-1\n");
			continue;
		}
		dfs(N);
		//开始枚举每一条边
//		for(res i=1;i<=N;i++){
//			printf("%d:",i); 
//			for(res j=0;j<pre[i].size();j++){
//				printf("%d ",pre[i][j]);
//			} 
//			printf("\n");
//		}
		ans=-inf;
		int flag=0;
		for(res i=1;i<=N;i++){
			for(res j=0;j<e[i].size();j++){
				int to=e[i][j];
				int temp1=dis[i][to],temp2;
				dis[i][to]=dis[to][i]=inf;
				temp2=dij2();
				if(-1==temp2){
					ans=-1;
					flag=1;
					break;
				} 
				ans=max(ans,temp2);
				dis[i][to]=dis[to][i]=temp1;
			}
			if(flag) break;
		} 
		printf("%d\n",ans);
	}
}

猜你喜欢

转载自blog.csdn.net/qq_41755258/article/details/85167053