HDU 4370 0 or 1 (最短路)

题意:

给出一个n*n的矩阵C,要求构造一个满足条件的n*n的01矩阵X,使得最小。

题解:

没错。。。第一眼怎么都觉得就是普通贪心,然后果断WA了。

正解是最短路。

由X矩阵的特点,可以看作是n个点的邻接矩阵,X[i][j]为1表示存在i到j的路径,C[i][j]就表示该路径的花费。

对X矩阵的要求可转化为,1号点出度为1(入度可能为0或1,更多显然),n号点入度为1(出度可以为0或1),其他点入度等于出度。

那么所求的答案就可能是,1号点直接到n号点的最短距离,或1号点形成一个回到1号点的环的最短距离+n号点形成一个回到n号点的环的最短距离。

代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define db double
#define m_p make_pair
#define p_b push_back
#define For(i,a,b) for(int i=a;i<=b;i++)
#define ls (root<<1)
#define rs ((root<<1)|1)
#define mst(a,b) memset(a,b,sizeof(a))
const int MAXN=3e2+5;
const db eps=1e-8;
const int INF=0x3f3f3f3f;
const int mod=1e9+7;
const int seed=131;
int a[MAXN][MAXN];
int dis[MAXN];
bool vis[MAXN];
struct Edge{
	int v,w;
	Edge(int _v=0,int _w=0):v(_v),w(_w){}
	bool operator<(const Edge &p)const{
		return w>p.w;
	}
};
priority_queue<Edge> pq;
void dij(int s,int n){
	mst(vis,0);
	For(i,1,n) if(i!=s) dis[i]=a[s][i],pq.push(Edge(i,dis[i]));
	dis[s]=INF;
	while(!pq.empty()){
		int u=pq.top().v;
		pq.pop();
		if(vis[u]) continue;
		vis[u]=1;
		for(int i=1;i<=n;i++){
			if(i!=u&&dis[i]>dis[u]+a[u][i]){
				dis[i]=dis[u]+a[u][i];
				pq.push(Edge(i,dis[i]));
			}
		}
	}
}
int main(){
//	freopen("in.txt","r",stdin);
	int n;
	while(~scanf("%d",&n)){
		For(i,1,n){
			For(j,1,n){
				scanf("%d",&a[i][j]);
			}
		}
		dij(1,n);
		int ans=dis[n],tmp=dis[1];
		dij(n,n);
		tmp+=dis[n];
		ans=min(ans,tmp);
		cout<<ans<<"\n";
	}
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_38515845/article/details/89736865