hdu4370

hdu4370 0 or 1
传送门

题意

给出一个\(n*n(1<n\leq 300)\)的矩阵\(C\),构造一个\(n*n\)\(01\)矩阵\(X\),满足条件:
\(1. X_{12}+X_{13}+\cdots +X_{1n}=1\)
\(2. X_{1n}+X_{2n}+\cdots +X_{n-1n}=1\)
\(3.\)对于每一个\(i,1<i<n\),有\(\sum X_{ki}=\sum X_{ij}(1\leq k\leq n,1\leq j\leq n)\)
计算\(\sum C_{ij}*X_{ij} (1\leq i,j \leq n)\)的最小值,也就是对所有\(X\)中为\(1\)的对应位置在\(C\)中的值求和的最小值

题解

\(C[i][j]\)看作图的邻接矩阵,也就是边的起点为\(i\),终点为\(j\),权值为\(C[i][j]\)
条件\(1\)表示\(1\)号节点的出度为\(1\)
条件\(2\)表示\(n\)号节点的入度为\(1\)
条件\(3\)表示其他节点的入度等于出度

等价于计算:
情况\(1\):从\(1\)\(n\)的最短路
情况\(2\):从\(1\)出发不经过\(n\)的最短闭环加上从\(n\)出发不经过\(1\)的最短闭环

\(ps.\)\(s\)出发的最短闭环的计算方法:在\(Dijkstra\)当中初始化时,设\(dis[s]=inf\),对于\(s\)所连的节点\(v\)\(dis[v]=C[s][v]\),之后进行\(Dijkstra\)\(dis[s]\)表示从\(s\)出发又回到\(s\)的最短闭环

#include<bits/stdc++.h>
#define LL long long
#define PII pair<int,int>
#define PLI pair<LL,int>
#define lson o<<1,l,mid
#define rson o<<1|1,mid+1,r
using namespace std;

const int maxn=310,inf=0x3f3f3f3f;
int n,C[maxn][maxn];
int dis[maxn];

void Dijkstra(int s){
	priority_queue<PII> pq;
	for(int i=1;i<=n;i++){
		dis[i]=inf;
	}
	for(int i=1;i<=n;i++){
		if(i!=s){
			dis[i]=C[s][i];
			pq.push({-dis[i],i});
		}
	}
	while(!pq.empty()){
		int d=pq.top().first;
		int u=pq.top().second;
		pq.pop();
		if(dis[u]<d) continue;
		for(int i=1;i<=n;i++){
			if(dis[i]>dis[u]+C[u][i]){
				dis[i]=dis[u]+C[u][i];
				pq.push({-dis[i],i});
			}
		}
	}
}

int main(){
	while(scanf("%d",&n)!=EOF){
		for(int i=1;i<=n;i++){
			for(int j=1;j<=n;j++){
				scanf("%d",&C[i][j]);
			}
		}
		Dijkstra(1);
		int ans=dis[n];
		int loop_1=dis[1];
		Dijkstra(n);
		int loop_n=dis[n];
		ans=min(ans,loop_1+loop_n);
		printf("%d\n",ans);
	}
}
posted @ 2020-08-13 20:28  fxq1304  阅读(1)  评论(0编辑  收藏  举报