bupt summer training for 16 #6 ——图论

https://vjudge.net/contest/174020

A.100条双向边,每个点最少连2个边

所以最多100个点,点的标号需要离散化

然后要求恰好经过n条路径

快速幂,乘法过程就是floyed就行了

 1 #include <algorithm>
 2 #include <cstring>
 3 #include <cstdio>
 4 
 5 using namespace std;
 6 
 7 const int maxn = 1010;
 8 
 9 int n, m, s, t, b, c[1001];
10 
11 struct matrix {
12     int c[101][101];
13     matrix() {
14         memset(c, 0x3f, sizeof c);
15     }
16     void add(int u, int v, int w) {
17         c[u][v] = c[v][u] = w;
18     }
19     matrix operator * (const matrix &a) const {
20         matrix b;
21         for(int k = 1;k <= n;k ++)
22             for(int i = 1;i <= n;i ++)
23                 for(int j = 1;j <= n;j ++)
24                     b.c[i][j] = min(b.c[i][j], c[i][k] + a.c[k][j]);
25         return b;
26     }
27     matrix operator ^ (int &k) {
28         matrix b = *this;
29         for(k --;k > 0;k >>= 1, *this = (*this) * (*this))
30             if(k & 1) b = b * (*this);
31         return b;
32     }
33 };
34 
35 int main() {
36     matrix g;
37     int u, v, w;
38     scanf("%d %d %d %d", &n, &m, &s, &t);
39     while(m --) {
40         scanf("%d %d %d", &w, &u, &v);
41         if(!c[u]) c[u] = ++ b;
42         if(!c[v]) c[v] = ++ b;
43         g.add(c[u], c[v], w);
44     }
45     swap(b, n);
46     printf("%d", (g ^ b).c[c[s]][c[t]]);
47     return 0;
48 }
View Code

B.

C.非常裸的生成树计数问题

其实谁是最高管理层并没什么卵用

想当然理解了读入,垃圾题目有重边

注意有重边,整数行列式计算可以拿来当板子了

 1 #include <algorithm>
 2 #include <cstring>
 3 #include <cstdio>
 4 
 5 using namespace std;
 6 
 7 const int maxn = 1010;
 8 
 9 int n, m, s, t, b, c[1001];
10 
11 struct matrix {
12     int c[101][101];
13     matrix() {
14         memset(c, 0x3f, sizeof c);
15     }
16     matrix(int x) {
17         memset(c, 0, sizeof c);
18         for(int i = 1;i <= n;i ++)
19             c[i][i] = 1;
20     }
21     void add(int u, int v, int w) {
22         c[u][v] = c[v][u] = w;
23     }
24     matrix operator * (const matrix &a) const {
25         matrix b;
26         for(int k = 1;k <= n;k ++)
27             for(int i = 1;i <= n;i ++)
28                 for(int j = 1;j <= n;j ++)
29                     b.c[i][j] = min(b.c[i][j], c[i][k] + a.c[k][j]);
30         return b;
31     }
32     matrix operator ^ (int &k) {
33         matrix b = *this;
34         for(k --;k > 0;k >>= 1, *this = (*this) * (*this))
35             if(k & 1) b = b * (*this);
36         return b;
37     }
38 };
39 
40 int main() {
41     matrix g;
42     int u, v, w;
43     scanf("%d %d %d %d", &n, &m, &s, &t);
44     while(m --) {
45         scanf("%d %d %d", &w, &u, &v);
46         if(!c[u]) c[u] = ++ b;
47         if(!c[v]) c[v] = ++ b;
48         g.add(c[u], c[v], w);
49     }
50     swap(b, n);
51     printf("%d", (g ^ b).c[c[s]][c[t]]);
52     return 0;
53 }
View Code

D.

E.高中做过的网络流模型

每行被隔开的算一块,st向这些块连边流量为1

因为这样一个块里最多放一个棋子

每列被隔开的算一块,这些块向en连边流量为1,道理同上

行块和列快相遇出可以放旗子,那么它们连一条边流量为1

因为只有一个位置

求个最大流...这样一说直接二分图上匈牙利就可以了...

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 
 5 using namespace std;
 6 
 7 const int maxn = 50010, maxm = 1000010, inf = 0x3f3f3f3f;
 8 
 9 int s, t, len = 1, g[maxn];
10 
11 struct edge {
12     int to, cap, next;
13 }e[maxm];
14 
15 int p[maxn], q[maxn], d[maxn];
16 
17 void add(int u, int v, int w) {
18     e[++ len] = (edge){v, w, g[u]}, g[u] = len;
19     e[++ len] = (edge){u, 0, g[v]}, g[v] = len;
20 }
21 
22 bool bfs() {
23     int l = 1, r = 1, x, i;
24     memset(d, 0, sizeof d);
25     d[s] = 1, q[1] = s;
26     while(l <= r) {
27         x = q[l ++];
28         for(i = g[x];i;i = e[i].next)
29             if(e[i].cap && !d[e[i].to])
30                 d[e[i].to] = d[x] + 1, q[++ r] = e[i].to;
31     }
32     return d[t];
33 }
34 
35 int dfs(int x, int y) {
36     if(x == t || y == 0) return y;
37     int flow = 0;
38     for(int &i = p[x];i;i = e[i].next) {
39         if(!e[i].cap  || d[e[i].to] != d[x] + 1) continue;
40         int f = dfs(e[i].to, min(y, e[i].cap));
41         flow += f, y -= f;
42         e[i].cap -= f, e[i ^ 1].cap += f;
43         if(!y) break;
44     }
45     return flow;
46 }
47 
48 int dinic() {
49     int maxflow = 0;
50     while(bfs()) {
51         memcpy(p, g, sizeof g);
52         maxflow += dfs(s, inf);
53     }
54     return maxflow;
55 }
56 
57 int n, m, cnt;
58 
59 char str[110][110];
60 
61 int mmp[110][110];
62 
63 int main() {
64     t = 10001;
65     while(~scanf("%d", &n)) {
66         m = 0;
67         memset(g, 0, sizeof g);
68         for(int  i = 1;i <= n;i ++)
69             scanf("%s", str[i] + 1);
70         for(int i = 1;i <= n;i ++) {
71             for(int j = 1;j <= n;j ++) {
72                 if(str[i][j] == 'X') mmp[i][j] = -1;
73                 else {
74                     if(j == 1 || str[i][j - 1] == 'X') m ++, add(s, m, 1);
75                     mmp[i][j] = m;
76                 }
77             }
78         }
79         for(int j = 1;j <= n;j ++)
80             for(int i = 1;i <= n;i ++) {
81                 if(str[i][j] != 'X') {
82                     if(i == 1 || str[i - 1][j] == 'X') m ++, add(m, t, 1);
83                     add(mmp[i][j], m, inf);
84                 }
85             }
86         printf("%d
", dinic());
87     }
88 }
View Code

F.裸的最短路,当然你要看到这是

单向边!!!

 1 #include <queue>
 2 #include <cstdio>
 3 #include <vector>
 4 #include <algorithm>
 5 
 6 using namespace std;
 7 
 8 const int maxn = 1010;
 9 
10 queue <int> q;
11 
12 int n, m, k, t, d[maxn], vis[maxn];
13 
14 vector <pair<int, int> > e[maxn];
15 
16 int main(){
17     while(~scanf("%d %d %d", &n, &m, &k)) {
18         for(int i = 1;i <= n;i ++) d[i] = 0x3f3f3f3f, e[i].clear();
19         for(int u, v, w, i = 1;i <= m;i ++) {
20             scanf("%d %d %d", &u, &v, &w);
21             e[u].push_back(make_pair(v, w));
22             //e[v].push_back(make_pair(u, w));
23         }
24         scanf("%d", &t);
25         for(int j, i = 1;i <= t;i ++)
26             scanf("%d", &j), d[j] = 0, q.push(j);
27         while(!q.empty()) {
28             int u = q.front();
29             q.pop(), vis[u] = 0;
30             for(int i = 0;i < e[u].size();i ++) {
31                 if(d[e[u][i].first] > d[u] + e[u][i].second) {
32                     d[e[u][i].first] = d[u] + e[u][i].second;
33                     if(!vis[e[u][i].first]) vis[e[u][i].first] = 1, q.push(e[u][i].first);
34                 }
35             }
36         }
37         printf("%d
", d[k] == 0x3f3f3f3f ? -1 : d[k]);
38     }
39     return 0;
40 }
View Code

G.裸MST,稠密图没有卡 Kruskal,良心!

 1 #include <cstdio>
 2 #include <algorithm>
 3 
 4 using namespace std;
 5 
 6 struct edge {
 7     int u, v, w;
 8     bool operator < (const edge &a) const {
 9         return w < a.w;
10     }
11 }e[10010];
12 
13 int n, f[110];
14 
15 int find_(int x) {
16     if(f[x] != x) return f[x] = find_(f[x]);
17     return x;
18 }
19 
20 int main() {
21     while(~scanf("%d", &n)) {
22         int m = 0, ans = 0;
23         for(int k, i = 1;i <= n;i ++) {
24             f[i] = i;
25             for(int j = 1;j <= i;j ++) scanf("%d", &k);
26             for(int j = i + 1;j <= n;j ++) scanf("%d", &k), e[++ m] = (edge){i, j, k};
27         }
28         sort(e + 1, e + m + 1);
29         for(int u, v, i = 1, j = 1;j < n;i ++) {
30             u = find_(e[i].u), v = find_(e[i].v);
31             if(u == v) continue;
32             f[v] = u, j ++, ans += e[i].w;
33         }
34         printf("%d
", ans);
35     }
36     return 0;
37 }
View Code

H.

I.经典网络流模型

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 
 5 using namespace std;
 6 
 7 const int maxn = 110, maxm = 50010, inf = 0x3f3f3f3f;
 8 
 9 int s, t, len = 1, g[maxn];
10 
11 struct edge {
12     int to, cap, next;
13 }e[maxm];
14 
15 int p[maxn], q[maxn], d[maxn];
16 
17 void add(int u, int v, int w) {
18     e[++ len] = (edge){v, w, g[u]}, g[u] = len;
19     e[++ len] = (edge){u, 0, g[v]}, g[v] = len;
20 }
21 
22 bool bfs() {
23     int l = 1, r = 1, x, i;
24     memset(d, 0, sizeof d);
25     d[s] = 1, q[1] = s;
26     while(l <= r) {
27         x = q[l ++];
28         for(i = g[x];i;i = e[i].next)
29             if(e[i].cap && !d[e[i].to])
30                 d[e[i].to] = d[x] + 1, q[++ r] = e[i].to;
31     }
32     return d[t];
33 }
34 
35 int dfs(int x, int y) {
36     if(x == t || y == 0) return y;
37     int flow = 0;
38     for(int &i = p[x];i;i = e[i].next) {
39         if(!e[i].cap  || d[e[i].to] != d[x] + 1) continue;
40         int f = dfs(e[i].to, min(y, e[i].cap));
41         flow += f, y -= f;
42         e[i].cap -= f, e[i ^ 1].cap += f;
43         if(!y) break;
44     }
45     return flow;
46 }
47 
48 int dinic() {
49     int maxflow = 0;
50     while(bfs()) {
51         memcpy(p, g, sizeof g);
52         maxflow += dfs(s, inf);
53     }
54     return maxflow;
55 }
56 
57 int Case, n, m, sum;
58 
59 int main() {
60     scanf("%d", &Case);
61     for(int tt = 1;tt <= Case;tt ++) {
62         sum = 0, len = 1;
63         memset(g, 0, sizeof g);
64         printf("Case #%d: ", tt);
65         scanf("%d %d", &n, &m), t = n + m + 1;
66         for(int j, i = 1;i <= n;i ++)
67             scanf("%d", &j), add(s, i, j), sum += j;
68         for(int j, i = 1;i <= m;i ++)
69             scanf("%d", &j), add(n + i, t, j);
70         for(int k, j, i = 1;i <= n;i ++) {
71             scanf("%d", &k);
72             while(k --) {
73                 scanf("%d", &j);
74                 add(i, n + j + 1, inf);
75             }
76         }
77         for(int k, i = 1;i <= m;i ++)
78             for(int j = 1;j <= m;j ++) {
79                 scanf("%d", &k);
80                 if(k) add(n + i, n + j, inf);
81             }
82         printf("%d
", sum - dinic());
83     }
84     return 0;
85 }
View Code

J.随便做的傻逼题,我写的算麻烦的

 1 #include <cstdio>
 2 #include <algorithm>
 3 
 4 using namespace std;
 5 
 6 int n, a[110];
 7 
 8 int main() {
 9     scanf("%d", &n);
10     for(int i = 1;i <= n;i ++)
11         scanf("%d", &a[i]);
12     int l = 1, r = n;
13     while(!a[l] && l <= n) l ++;
14     while(!a[r] && r >= 1) r --;
15     if(l > r) puts("0");
16     else {
17         int ans = 1, last = 1;
18         for(int i = l + 1;i <= r;i ++) {
19             if(a[i]) {
20                 ans ++;
21                 if(last != 1) last = 1;
22             }
23             else {
24                 if(last != 0) {
25                     if(i < r && !a[i + 1]) last = 0;
26                     else ans ++;
27                 }
28             }
29         }
30         printf("%d
", ans);
31     }
32     return 0;
33 }
View Code
原文地址:https://www.cnblogs.com/ytytzzz/p/7253875.html