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 }

 

posted @ 2021-01-22 22:23  acmloser  阅读(53)  评论(0编辑  收藏  举报