0 or 1 HDU - 4370
考察:思维+最短路
给我100小时都想不出这种操作
根据题意:
要求1可转化成1只有一个出度
要求2可转化成4只有一个入度
要求3可转成2~n-1入度=出度
要求答案最小,也就是1尽可能少,0尽可能多.即求边同时也要保证1也就是边的权值最小.这就是最短路问题
如果1->n权值和最小,则答案是1->n的最短路(中间可能经过其他点,但在最短路中,中间点的入度=出度)
但根据题目条件,对1的入度是没有要求的,同理4的出度也没有要求.所以答案可以分类为1->n和1->非n,但要求其他点入度=出度,那么其他点只能做中间点.所以答案是1->a...->1+n->a..->n或1->...->n
本蒟蒻不会求最小环,看大佬的代码,可以将dist[原点]赋值为无穷大,其他点为原点到该点的距离,其他点全入队,这样就既能求出最小环也能求出到其他点的最短路
(本题不是我们自己建的图,所以我们不知道1不能到哪些点,只能全部入队)
1 #include <iostream> 2 #include <queue> 3 #include <cstring> 4 #include <algorithm> 5 using namespace std; 6 const int N = 310; 7 int n,g[N][N],dist[N]; 8 bool st[N]; 9 void spfa(int s) 10 { 11 memset(st,0,sizeof st); 12 queue<int> q; 13 for(int i=1;i<=n;i++) 14 { 15 if(i==s) dist[i] = 0x3f3f3f3f; 16 else dist[i] = g[s][i],q.push(i),st[i] = 1; 17 } 18 while(q.size()) 19 { 20 int t = q.front(); 21 st[t] = 0; 22 q.pop(); 23 for(int i=1;i<=n;i++) 24 { 25 if(dist[i]>dist[t]+g[t][i]) 26 { 27 dist[i] = dist[t]+g[t][i]; 28 if(!st[i]) q.push(i),st[i] = 1; 29 } 30 } 31 } 32 } 33 int main() 34 { 35 // freopen("in.txt","r",stdin); 36 while(scanf("%d",&n)!=EOF) 37 { 38 for(int i=1;i<=n;i++) 39 for(int j=1;j<=n;j++) 40 scanf("%d",&g[i][j]); 41 spfa(1); 42 int a = dist[n],b = dist[1]; 43 spfa(n); 44 int c = dist[n]; 45 printf("%d\n",min(a,b+c)); 46 } 47 return 0; 48 }