HDU-1853 Cyclic Tour

HDU-1853

题意:有n个城市, m条单向路, 这个路有长度, 现在需要将这n个城市分成几个环, 这几个环不能有相交的城市, 求出最小的总长度。

题解:在一个单项环中,每个城市都只会被一条路指到,所以用KM算法跑出最小费用就好了。

注意的就是题目会给出重边。

代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
 4 #define LL long long
 5 #define ULL unsigned LL
 6 #define fi first
 7 #define se second
 8 #define pb push_back
 9 #define lson l,m,rt<<1
10 #define rson m+1,r,rt<<1|1
11 #define max3(a,b,c) max(a,max(b,c))
12 #define min3(a,b,c) min(a,min(b,c))
13 typedef pair<int,int> pll;
14 const int inf = 0x3f3f3f3f;
15 const LL INF = 0x3f3f3f3f3f3f3f3f;
16 const LL mod =  (int)1e9+7;
17 const int N = 110;
18 int val[N][N];
19 int lx[N], ly[N], match[N];
20 int visx[N], visy[N];
21 int slack[N];
22 int n, m;
23 void init(){
24     memset(match, -1, sizeof(match));
25     memset(ly, 0, sizeof(ly));
26     //memset(lx, -inf, sizeof(lx));
27     //memset(val, -inf, sizeof(val));
28     for(int i = 1; i <= n; i++){
29         lx[i] = -inf;
30         for(int j = 1; j <= n; j++)
31             val[i][j] = -inf;
32     }
33 
34 }
35 bool hunger(int u){
36     visx[u] = 1;
37     for(int i = 1; i <= n; i++){
38         if(visy[i] || val[u][i] == -inf) continue;
39         else {
40             if(lx[u] + ly[i] == val[u][i]){
41                 visy[i] = 1;
42                 if(match[i] == -1 || hunger(match[i])){
43                     match[i] = u;
44                     return true;
45                 }
46             }
47             else slack[i] = min(slack[i], lx[u]+ly[i] - val[u][i]);
48         }
49     }
50     return false;
51 
52 }
53 int KM_perferct_match(){
54     /*for(int i = 1; i <= n; i++)
55         for(int j = 1; j <= n; j++)
56             if(val[i][j] != -inf)
57                 lx[i] = max(lx[i], val[i][j]);*/
58     for(int i = 1; i <= n; i++){
59         memset(slack, inf, sizeof(slack));
60         while(1){
61             memset(visx, 0, sizeof(visx));
62             memset(visy, 0, sizeof(visy));
63             if(hunger(i)) break;
64             else {
65                 int tmp = inf;
66                 for(int j = 1; j <= n; j++)
67                     if(!visy[j]) tmp = min(tmp, slack[j]);
68                 if(tmp == inf) return 1;
69                 for(int j = 1; j <= n; j++){
70                     if(visx[j]) lx[j] -= tmp;
71                     if(visy[j]) ly[j] += tmp;
72                 }
73             }
74         }
75     }
76     int ans = 0;
77     for(int i = 1; i <= n; i++)
78         if(match[i] != -1) ans += val[match[i]][i];
79     return ans;
80 }
81 int main(){
82     while(~scanf("%d%d", &n, &m)){
83         init();
84         while(m--){
85             int a, b, c;
86             scanf("%d%d%d", &a, &b, &c);
87             val[a][b] = max(val[a][b], -c);
88             lx[a] = max(lx[a], val[a][b]);
89         }
90         printf("%d\n", -KM_perferct_match());
91     }
92     return 0;
93 }
View Code

emm, 第一次知道, memset(a, -inf, sizeof(a)) 后 a[0] != -inf;

转载于:https://www.cnblogs.com/MingSD/p/9310015.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值