HDU4370(思維最短路徑)
Problem Description
Given a nn matrix Cij (1<=i,j<=n),We want to find a nn matrix Xij (1<=i,j<=n),which is 0 or 1.
Besides,Xij meets the following conditions:
1.X12+X13+…X1n=1
2.X1n+X2n+…Xn-1n=1
3.for each i (1<i<n), satisfies ∑Xki (1<=k<=n)=∑Xij (1<=j<=n).
For example, if n=4,we can get the following equality:
X12+X13+X14=1
X14+X24+X34=1
X12+X22+X32+X42=X21+X22+X23+X24
X13+X23+X33+X43=X31+X32+X33+X34
Now ,we want to know the minimum of ∑Cij*Xij(1<=i,j<=n) you can get.
Hint
For sample, X12=X24=1,all other Xij is 0.
Input
The input consists of multiple test cases (less than 35 case).
For each test case ,the first line contains one integer n (1<n<=300).
The next n lines, for each lines, each of which contains n integers, illustrating the matrix C, The j-th integer on i-th line is Cij(0<=Cij<=100000).
Output
For each case, output the minimum of ∑Cij*Xij you can get.
Sample Input
4
1 2 4 10
2 0 1 1
2 2 0 5
6 3 1 2
Sample Output
3
Author
Snow_storm
Source
2012 Multi-University Training Contest 8
題意:
給你一個二維矩陣讓你建立一個新的二維矩陣X使得:
1.X12+X13+…X1n=1
2.X1n+X2n+…Xn-1n=1
3.for each i (1<i<n), satisfies ∑Xki (1<=k<=n)=∑Xij (1<=j<=n).
求 ∑Cij*Xij(1<=i,j<=n)最小值題解:
可以把這個矩陣看成一個有向圖條件1和條件2 表示定點1的出度為1 定點n的入度為1
其他點的入度與出度相等
就可以轉化為二種可能:
1:求1到n的最短距離
2:1和n都分別各自組成一個環求這個兩個環上的邊和
答案:去上面的最小值
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<cmath>
#include<queue>
using namespace std;
#define clr(a,b) memset(a,b,sizeof(a))
#define il inline
#define eb(a) emplace_back (a)
#define pb(a) push_back(a)
typedef long long ll;
const int maxn=310+2;
const int minn=100+4;
const int inf=0x3f3f3f3f3f;
int n,vis[maxn],dis[maxn],mat[maxn][maxn];
queue<int> qu;
il void spfa(int a)
{
clr(vis,0);
for(int i=1;i<=n;++i)//預處理到每個定點的值因為要求a到a環的大小
{
if(i!=a)
{
qu.emplace(i);
vis[i]=1;
dis[i]=mat[a][i];
}
}
dis[a]=inf;
while(!qu.empty())
{
int nu=qu.front();qu.pop();vis[nu]=0;
for(int i=1;i<=n;++i)
{
if(i==nu){continue;}//因為再當中到其本身是木有意義的
int tv=mat[nu][i];
if(dis[i]>dis[nu]+mat[nu][i])
{
dis[i]=dis[nu]+mat[nu][i];
if(!vis[nu])
{
vis[i]=1;
qu.emplace(i);
}
}
}
}
return ;
}
int main()
{
while(~scanf("%d",&n))
{
for(int i=1;i<=n;++i)
{
for(int j=1;j<=n;++j)
{
scanf("%d",&mat[i][j]);
}
}
spfa(1);
int ans=dis[n];
int res1=dis[1];
spfa(n);
int res2=dis[n];
printf("%d\n",min(ans,res1+res2));//輸出兩個中最小的那個
}
return 0;
}