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);
}
}