爬格子呀9.17(图论)

刘汝佳的紫书差不多就告一段落吧,我觉得可以了,怎么说呢,这书也陪着自己走了一年多了吧,也目睹了从一个啥也不会的萌新到一个稍微会一点的萌新的转变。

差不多开始下本书吧,自己也大三了,时间真的有点紧啊woctm

最喜欢的图论作为自己对这本书的谢幕,也好,也好



uva10735(欧拉回路+网络流)

题意:给一个图,图中有部分是向边,部分是无向边,要求判断是否存在欧拉回路,若存在,输出路径

解法:

  1 #include<bits/stdc++.h>
  2 #define REP(i, a, b) for(int i = (a); i < (b); i++)
  3 #define MEM(a,x) memset(a,x,sizeof(a))
  4 #define INF 0x3f3f3f3f
  5 #define MAXN 10000+10
  6 using namespace std;
  7
  8 struct Euler
  9 {
 10     struct Edge {
 11         int to, nxt;
 12         Edge() {}
 13         Edge(int x, int y) :to(x), nxt(y) {}
 14     }edges[MAXN];
 15     int head[MAXN], n, E;
 16     void init(const int &n) {
 17         this->n = n; E = 0;
 18         for (int i = 0; i <= n; i++)head[i] = -1;
 19     }
 20     void AddEdge(int f, int t) {
 21         edges[++E] = Edge(t, head[f]);
 22         head[f] = E;
 23     }
 24     stack<int >S;
 25     bool vis[MAXN];//use when dfs
 26     void dfs(int x) {//get EulerCircle
 27         Edge e;
 28         for (int i = head[x]; i != -1; i = e.nxt) {
 29             e = edges[i];
 30             if (vis[i])continue;
 31             vis[i] = 1;
 32             dfs(e.to);
 33             S.push(x);
 34         }
 35     }
 36     void getEulerCircle() {
 37         while (!S.empty())S.pop();
 38         memset(vis, 0, sizeof(vis));
 39         dfs(1);
 40         for (; !S.empty(); S.pop()) {
 41             printf("%d ", S.top());
 42         }
 43         puts("1");
 44     }
 45 }gg;
 46
 47 struct Dinic
 48 {
 49     struct Edge {
 50         int from, to, cap, flow;
 51         Edge(int u, int v, int c, int f) :
 52             from(u), to(v), cap(c), flow(f) {}
 53     };
 54     int n, s, t;
 55     vector<Edge>edges;
 56     vector< int>G[MAXN]; //gragh
 57     bool vis[MAXN]; //use when bfs
 58     int d[MAXN], cur[MAXN];//dist,now edge,use in dfs
 59     void AddEdge(int from, int to, int cap) {
 60         edges.push_back(Edge(from, to, cap, 0));
 61         edges.push_back(Edge(to, from, 0, 0));
 62         int top = edges.size();
 63         G[from].push_back(top - 2);
 64         G[to].push_back(top - 1);
 65     }
 66     void init(int n, int s, int t) {
 67         this->n = n;
 68         this->s = s;
 69         this->t = t;
 70         edges.clear();
 71         for (int i = 0; i <= n; i++)G[i].clear();
 72     }
 73
 74     bool BFS() {
 75         memset(vis, 0, sizeof(vis));
 76         queue<int>Q;
 77         Q.push(s); d[s] = 0; vis[s] = 1;
 78         while (!Q.empty()) {
 79             int x = Q.front(); Q.pop();
 80             for (int i = 0; i < G[x].size(); i++) {
 81                 Edge &e = edges[G[x][i]];
 82                 if (vis[e.to] || e.cap <= e.flow)continue;
 83                 vis[e.to] = 1;
 84                 d[e.to] = d[x] + 1;
 85                 Q.push(e.to);
 86             }
 87         }
 88         return vis[t];
 89     }
 90     int DFS(const int& x, int a) {
 91         if (x == t || a == 0) { return a; }
 92         int flow = 0, f;
 93         for (int& i = cur[x]; i < G[x].size(); i++) {
 94             Edge& e = edges[G[x][i]];
 95             if (d[x] + 1 != d[e.to])continue;
 96             if ((f = DFS(e.to, min(a, e.cap - e.flow))) <= 0)continue;
 97             e.flow += f;
 98             edges[G[x][i] ^ 1].flow -= f;//??
 99             flow += f; a -= f;
100             if (!a) break;
101         }
102         return flow;
103     }
104     int MaxFlow(int s, int t) {
105         int flow = 0;
106         for (; BFS();) {
107             memset(cur, 0, sizeof(cur));
108             flow += DFS(s, INF);
109         }
110         return flow;
111     }
112     void buildEuler(int n) {
113         for (int i = 1; i <= n; i++) {
114             for (int j = 0; j < G[i].size(); j++) {
115                 Edge &e = edges[G[i][j]];
116                 if (e.to == s || e.to == t) continue;
117                 if (!e.cap)continue;
118                 if (e.flow == e.cap)gg.AddEdge(e.to, e.from);
119                 else gg.AddEdge(e.from, e.to);
120             }
121         }
122     }
123 }g;
124
125 int d[MAXN];//degree = out - in
126 bool work(int n) {
127     int flow = 0;
128     REP(i, 1, n + 1) {
129         if (d[i] & 1)return 0;
130         if (d[i] > 0) {
131             g.AddEdge(g.s, i, d[i] >> 1);
132             flow += d[i] >> 1;
133         }
134         else if (d[i] < 0)
135             g.AddEdge(i, g.t, -(d[i] >> 1));
136     }
137     if (flow != g.MaxFlow(0, n + 1)) return 0;
138     return 1;
139 }
140
141 int main() {
142     int T, x, y, n, m;
143     scanf("%d", &T);
144     for (char ch; T--;) {
145         scanf("%d%d", &n, &m);
146         g.init(n, 0, n + 1);
147         gg.init(n);
148         MEM(d, 0);
149         REP(i, 0, m) {
150             scanf("%d %d %c", &x, &y, &ch);
151             if (ch == ‘D‘) gg.AddEdge(x, y);
152             else g.AddEdge(x, y, 1);
153             d[x]++; d[y]--;//Degree
154         }
155         if (!work(n))puts("No euler circuit exist");
156         else {
157             g.buildEuler(n);
158             gg.getEulerCircle();
159         }
160         if (T)puts("");
161     }
162     return 0;
163 }


uva1001

题意:

给出一些球,球内的时间为零,球之间的速度为10每单位。给两个点,求最短时间。

解法:

处理出任意两点之间的距离 && 做题的时候要大胆点hhh

 1 #include<bits/stdc++.h>
 2 #define REP(i, a, b) for(int i = (a); i < (b); i++)
 3 #define MEM(a,x) memset(a,x,sizeof(a))
 4 #define INF 0x3f3f3f3f
 5 #define MAXN 100+10
 6 using namespace std;
 7 struct node { int x, y, z, r; }p[MAXN];
 8 double g[MAXN][MAXN];
 9
10 double dis(node a,node b) {
11     double ans = sqrt(
12           (a.x - b.x)*(a.x - b.x)
13         + (a.y - b.y)*(a.y - b.y)
14         + (a.z - b.z)*(a.z - b.z))
15         - (a.r + b.r);
16     return ans < 0 ? 0 : ans;
17 }
18
19 int main() {
20     int n, cnt = 0;
21     while (cin >> n && n != -1) {
22         REP(i, 0, n) cin >> p[i].x >> p[i].y >> p[i].z >> p[i].r;
23         cin >> p[n].x >> p[n].y >> p[n].z; p[n].r = 0;
24         cin >> p[n + 1].x >> p[n + 1].y >> p[n + 1].z; p[n + 1].r = 0;
25
26         MEM(g, INF);
27         REP(i, 0, n + 2)g[i][i] = 0;
28         REP(i, 0, n + 2)REP(j, 0, n + 2) g[i][j] = dis(p[i], p[j]);
29
30         REP(k, 0, n + 2)REP(i, 0, n + 2)REP(j, 0, n + 2)
31             g[i][j] = min(g[i][j], g[i][k] + g[k][j]);
32
33         g[n][n + 1] *= 10;
34         printf("Cheese %d: Travel time = %.0f sec\n", ++cnt, g[n][n + 1]);
35     }
36     return 0;
37 }


uva820

题意:有一个计算机网络,输入节点数n,输入网络流源点和汇点src,des,再输入双向边数m。给出m条边的负载,求最大流。

解法:

网络流模板题

你想,流量其实就是运输物品,我们要求的就是从源点到汇点最多能运输多少单位的物品,

当物品变成水流的时候,他可以均匀的分布在所有边上,每个边上可以有的物品数就是这个边的容量,所有可行边的路径和就是我们要求的所谓“路径权值和”

这道题Dinic中的init有问题,改了一下就好了

 1 #include<bits/stdc++.h>
 2 #define REP(i, a, b) for(int i = (a); i < (b); i++)
 3 #define MEM(a,x) memset(a,x,sizeof(a))
 4 #define INF 0x3f3f3f3f
 5 #define MAXN 1000+10
 6 using namespace std;
 7 struct Edge {
 8     int from, to, cap, flow;
 9 };
10 struct Dinic {
11     int n, m, s, t;
12     vector<Edge>edges;
13     vector<int>G[MAXN];
14     bool vis[MAXN];
15     int d[MAXN];
16     int cur[MAXN];
17     void init() {
18         edges.clear();
19         for (int i = 0; i < MAXN; i++) G[i].clear();
20         memset(d, 0, sizeof d);
21     }
22     void AddEdge(int from, int to, int cap) {
23         edges.push_back({ from, to, cap, 0 });
24         edges.push_back({ to, from, 0, 0 });
25         m = edges.size();
26         G[from].push_back(m - 2);
27         G[to].push_back(m - 1);
28     }
29     bool BFS() {
30         int x, i;
31         memset(vis, 0, sizeof(vis));
32         queue<int>Q;
33         Q.push(s);
34         d[s] = 0;
35         vis[s] = 1;
36         while (!Q.empty()) {
37             x = Q.front(), Q.pop();
38             for (i = 0; i < G[x].size(); i++) {
39                 Edge & e = edges[G[x][i]];
40                 if (!vis[e.to] && e.cap > e.flow) {
41                     vis[e.to] = 1;
42                     d[e.to] = d[x] + 1;
43                     Q.push(e.to);
44                 }
45             }
46         }
47         return vis[t];
48     }
49     int DFS(int x, int a) {
50         if (x == t || a == 0)
51             return a;
52         int flow = 0, f;
53         for (int &i = cur[x]; i < G[x].size(); i++) {
54             Edge & e = edges[G[x][i]];
55             if (d[x] + 1 == d[e.to] && (f = DFS(e.to, min(a, e.cap - e.flow))) > 0) {
56                 e.flow += f;
57                 edges[G[x][i] ^ 1].flow -= f;
58                 flow += f;
59                 a -= f;
60                 if (a == 0)
61                     break;
62             }
63         }
64         return flow;
65     }
66     int Maxflow(int s, int t) {
67         this->s = s, this->t = t;
68         int flow = 0;
69         while (BFS()) {
70             memset(cur, 0, sizeof(cur));
71             flow += DFS(s, INF);
72         }
73         return flow;
74     }
75 }Men;
76 int main() {
77     int n, kase = 0;
78     while (scanf("%d", &n) && n) {
79         int s, t, c, u, v, w;
80         Men.init();
81         scanf("%d%d%d", &s, &t, &c);
82         REP(i, 0, c) {
83             scanf("%d%d%d", &u, &v, &w);
84             Men.AddEdge(u, v, w);
85             Men.AddEdge(v, u, w);
86         }
87         printf("Network %d\nThe bandwidth is %d.\n\n", ++kase, Men.Maxflow(s, t));
88     }
89     return 0;
90 }


uva10801

题意:

一个人在大楼的0楼,大楼最多到99层。有n部电梯,每部电梯有可到达的楼层,每个电梯移动一层的时间为T[i]秒。换电梯的时间为60秒。

给你一个楼层,问你电梯到这个楼层的最短路径。

解法:

很容易看出是一个最短路问题,关键在于如何建图,

首先我们分析一下我们很容易想到把楼层当作点把时间当左边,但是有一个问题由于它涉及楼层中换电梯所以这样做的话我们就无法计算换电梯的时间,所以我的方法是把一个楼层拆成n个点(这样做的前提是在这道题中n比较小<=5)分别表示从哪一个电梯下来的。然后再把相同楼层的点之间加一条长度为60的边。

这样再通过执行n次Dijkstra算法去最小值得出答案。(或者直接Floyd)

 1 #include<bits/stdc++.h>
 2 #define REP(i, a, b) for(int i = (a); i < (b); i++)
 3 #define MEM(a,x) memset(a,x,sizeof(a))
 4 #define INF 0x3f3f3f3f
 5 #define MAXN 100+10
 6 using namespace std;
 7 int t[MAXN], num[MAXN];
 8 int g[MAXN][MAXN];
 9
10 void AddEdge(int i, int j, int s) {
11     g[i][j] = g[j][i] = min(min(g[i][j], g[j][i]), abs(i - j)*s);
12     return;
13 }
14
15 int main() {
16     int n, k;
17     while (scanf("%d%d", &n, &k) != EOF) {
18         MEM(g, INF);
19         REP(i, 0, n)scanf("%d", &t[i]);
20         int UP = -1;
21         REP(i, 0, n) {
22             char ch = ‘\0‘;
23             for (int j = 0; ch != ‘\n‘; j++) {
24                 scanf("%d%c", &num[j], &ch);
25                 UP = max(UP, num[j]);
26                 REP(k, 0, j) AddEdge(num[j], num[k], t[i]);
27             }
28         }
29
30         UP++;
31         REP(i, 0, UP)g[i][i] = 0;
32         REP(k, 0, UP)REP(i, 0, UP)REP(j, 0, UP)
33             g[i][j] = min(g[i][j], g[i][k] + g[k][j] + 60);
34
35         if (k == 0)printf("0\n");
36         else if (g[0][k] == INF)printf("IMPOSSIBLE\n");
37         else printf("%d\n", g[0][k]);
38     }
39     return 0;
40 }


uva1663

题意:

给出一些01串,含星号的串表示包含两个串,星号位置分别为0和1。 
每次可以消掉一个串或者两个只有一个数字不同的串,求最少几次可以消掉所有串。

解法:

读出所有串,两两判断能否一起消掉,然后其最大匹配数即可。具体细节见代码。

这道题的建图挺有意思的

 1 #include<bits/stdc++.h>
 2 #define REP(i, a, b) for(int i = (a); i < (b); i++)
 3 #define CLR(a) memset(a,0,sizeof(a));
 4 #define MEM(a,x) memset(a,x,sizeof(a))
 5 #define ALL(x) begin(x),end(x)
 6 #define INF 0x3f3f3f3f
 7 #define MAXN 2000+10
 8 #define LL long long
 9 using namespace std;
10
11 int Set[MAXN], n, m;
12 char s[20];
13
14 int g[MAXN][MAXN], match[MAXN], vis[MAXN];
15 bool dfs(int u) {
16     for (int i = 0; i < MAXN; i++) {
17         if (g[u][i] && !vis[i]) {
18             vis[i] = 1;
19             if (match[i] == -1 || dfs(match[i])) {
20                 match[i] = u;
21                 return true;
22             }
23         }
24     }
25     return false;
26 }
27
28 int Hungarian(){
29     int ans = 0;
30     memset(match, -1, sizeof(match));
31     for (int i = 0; i < MAXN; i++){
32         memset(vis, 0, sizeof(vis));
33         if (dfs(i))ans++;
34     }
35     return ans;
36 }
37
38 int main() {
39     while (scanf("%d%d", &n, &m) && (n+m)) {
40         CLR(g); CLR(Set); CLR(vis);
41         REP(i, 0, m) {
42             scanf("%s", s);
43             int pos = -1, tmp = 0;
44             REP(j, 0, n) {
45                 if (s[j] == ‘1‘)tmp |= 1 << j;
46                 else if (s[j] == ‘*‘)pos = j;
47             }
48             Set[tmp] = 1;
49             if (pos != -1) {//将*拆分成0和1两种
50                 tmp |= 1 << pos;
51                 Set[tmp] = true;
52             }
53         }
54         m = 0;
55         REP(i, 0, MAXN) {
56             if (Set[i]) {
57                 m++;
58                 REP(j, 0, n) {
59                     int tmp = i ^ (1 << j);//只有一位不同
60                     if (Set[tmp])g[i][tmp] = true;
61                 }
62             }
63         }
64         printf("%d\n", m - Hungarian() / 2);
65     }
66     return 0;
67 }


uva12549

题意:

在一个Y行X列的网格里有空地(.),重要位置(*)和障碍物(#),用最少的机器人看守所有重要位置,每个机器人要放在一个格子里,面朝上下左右4个方向之一。

机器人会发出激光,一直射到障碍物为止,沿途都是看守范围。

解法:

首先肯定是二分图最大匹配;其次如果没有障碍物的话,直接每个目标的x和y建表跑匈牙利即可;

但这个题目中他有障碍物,我们就横纵坐标分块即可(相当于离散化),之后匈牙利

 1 #include<bits/stdc++.h>
 2 #define REP(i, a, b) for(int i = (a); i < (b); i++)
 3 #define CLR(a) memset(a,0,sizeof(a));
 4 #define MEM(a,x) memset(a,x,sizeof(a))
 5 #define ALL(x) begin(x),end(x)
 6 #define INF 0x3f3f3f3f
 7 #define MAXN 100+10
 8 #define MAXM 2005
 9 #define LL long long
10 using namespace std;
11
12 int g[MAXM][MAXM], match[MAXM], vis[MAXM];
13 int mp[MAXN][MAXN], X[MAXN][MAXN], Y[MAXN][MAXN];
14 int xcnt, ycnt;
15 bool dfs(int u) {
16     for (int i = 0; i < ycnt; i++) {
17         if (g[u][i] && !vis[i]) {
18             vis[i] = 1;
19             if (match[i] == -1 || dfs(match[i])) {
20                 match[i] = u;
21                 return true;
22             }
23         }
24     }
25     return false;
26 }
27
28 int Hungarian() {
29     int ans = 0;
30     memset(match, -1, sizeof(match));
31     for (int i = 0; i < xcnt; i++) {
32         memset(vis, 0, sizeof(vis));
33         if (dfs(i))ans++;
34     }
35     return ans;
36 }
37
38 int main() {
39     int T; scanf("%d", &T);
40     while (T--) {
41         CLR(g); CLR(mp); CLR(X); CLR(Y);
42         getchar();
43         int n, m; scanf("%d%d", &n, &m);
44
45         int p, x, y;
46         scanf("%d", &p);
47         REP(i, 0, p) { scanf("%d %d", &x, &y); mp[x-1][y-1] = 1; }
48         scanf("%d", &p);
49         REP(i, 0, p) { scanf("%d %d", &x, &y); mp[x-1][y-1] = 2; }
50
51         xcnt = -1;
52         REP(i, 0, n) {
53             bool flag = true;
54             REP(j, 0, m) {
55                 if (mp[i][j] == 1) {
56                     if (flag)xcnt++;
57                     X[i][j] = xcnt;
58                     flag = false;
59                 }
60                 else if(mp[i][j]==2)
61                     flag = true;
62             }
63         }
64         ycnt = -1;
65         REP(i, 0, n) {
66             bool flag = true;
67             REP(j, 0, m) {
68                 if (mp[j][i] == 1) {
69                     if (flag)ycnt++;
70                     Y[j][i] = ycnt;
71                     flag = false;
72                 }
73                 else if (mp[j][i] == 2)
74                     flag = true;
75             }
76         }
77         xcnt++, ycnt++;
78
79         REP(i, 0, n)REP(j, 0, m)if(mp[i][j]==1)
80             g[X[i][j]][Y[i][j]] = 1;
81         printf("%d\n", Hungarian());
82     }
83     return 0;
84 }


uva1664

题意:

给你n个点,接着给你n-1条边形成一颗生成树,每条边都有一个权值。

求的是以一个点作为特殊点,并求出从此点出发到其他每个点的条件边权的总和最大,条件边权就是:起点到终点经过的权值的最小值。

解法:

非常巧妙的并查集;真的没有想到;

首先我们把要选的那个结点看作是我们的根节点,用Kruscal的思想,首先给所有边按照从大到小的顺序排序,

之后我们遍历每条边,该边的两个顶点所在的集合设为A、B,集合A、B的顶点a、b,要让谁当中心点呢?

易知:无论谁当中心点,它与另一个集合中任一点的容量都为该边长度(因为是从大到小枚举的)。

那么为了求出总容量,我们要维护一些值,用空间换时间 。

维护每个顶点的总容量sum[i],维护每个顶点与之相连的顶点数量,cnt[i],当前答案ans 。

那么对于a、b点,如果以a为中心,总容量为sum[a] + cnt[b] * e[i].c 。

反之亦然,哪个量大,则以哪个点为城市中心,也就是并查集的根结点 。

 1 #include<bits/stdc++.h>
 2 #define REP(i, a, b) for(int i = (a); i < (b); i++)
 3 #define CLR(a) memset(a,0,sizeof(a));
 4 #define MEM(a,x) memset(a,x,sizeof(a))
 5 #define ALL(x) begin(x),end(x)
 6 #define LL long long
 7 const int INF = 0x3f3f3f3f;
 8 const int MAXN = 200000 + 10;
 9 using namespace std;
10
11 struct edge {
12     int u, v, w;
13     bool operator < (const edge& rhs) const {
14         return w > rhs.w;
15     }
16 }e[MAXN];
17 LL p[MAXN], sum[MAXN], cnt[MAXN];
18 int findSet(int x) { return p[x] == x ? x : p[x] = findSet(p[x]); }
19 int main() {
20     int n;
21     while (scanf("%d", &n) != EOF) {
22         REP(i, 0, n - 1) {scanf("%d%d%d", &e[i].u, &e[i].v, &e[i].w);}
23         REP(i, 1, n+1) {p[i] = i; sum[i] = 0; cnt[i] = 1;}
24         sort(e, e + n - 1);
25         LL ans = 0;
26         REP(i, 0, n - 1) {
27             int x = findSet(e[i].u), y = findSet(e[i].v);
28             LL sumu = sum[x] + cnt[y] * e[i].w;
29             LL sumv = sum[y] + cnt[x] * e[i].w;
30             if (sumu < sumv) {
31                 p[x] = y; cnt[y] += cnt[x];
32                 ans = sum[y] = sumv;
33             }
34             else {
35                 p[y] = x; cnt[x] += cnt[y]; sum[x] = sumu;
36                 ans = sum[x] = sumu;
37             }
38         }
39         printf("%lld\n", ans);
40     }
41     return 0;
42 }


uva1668(建图)

题意:

给定一棵有 nn 个节点的树,每条边有边权 w(u,v)w(u,v),用最小的路径覆盖所有的边,使得每条边被覆盖的次数等于其边权。

解法:

这道题考的是思维。

首先我们求出所有点的权值之和,就是我们要求的答案的最大值;再求出每个点的最大权值,依次看其是否超过总权值的一半;

如果超过的话,我们就直接减去最大权值,代表不能全部合并; 否则,我们就减去总权值的一半,代表能全部合并;

 1 #include<bits/stdc++.h>
 2 #define REP(i, a, b) for(int i = (a); i < (b); i++)
 3 #define CLR(a) memset(a,0,sizeof(a));
 4 #define MEM(a,x) memset(a,x,sizeof(a))
 5 #define ALL(x) begin(x),end(x)
 6 #define LL long long
 7 #define INF 0x3f3f3f3f
 8 #define MAXN 100000 + 10
 9 using namespace std;
10
11 int deg[MAXN], maxd[MAXN];
12 int  main() {
13     int T; scanf("%d", &T);
14     int kase = 0;
15     while (T--) {
16         CLR(deg); CLR(maxd);
17         int n; scanf("%d", &n);
18         int u, v, w;
19         LL ans = 0;
20         REP(i, 1, n) {
21             scanf("%d%d%d", &u, &v, &w);
22             deg[u] += w, deg[v] += w;
23             maxd[u] = max(maxd[u], w);
24             maxd[v] = max(maxd[v], w);
25             ans += w;
26         }
27         REP(i, 1, n+1) {
28             if ((maxd[i] << 1) <= deg[i])
29                 ans -= deg[i] >> 1;
30             else
31                 ans -= deg[i] - maxd[i];
32         }
33         printf("Case #%d: %lld\n", ++kase, ans);
34     }
35     return 0;
36 }

原文地址:https://www.cnblogs.com/romaLzhih/p/9661331.html

时间: 2024-11-08 20:25:59

爬格子呀9.17(图论)的相关文章

AnimeGAN输出日志

D:\MyFiles\LearnFiles\Code\Python\AnimeGAN\AnimeGAN>python main.py --phase train --dataset Hayao --epoch 1 --init_epoch 1D:\Users\feng_\AppData\Local\Programs\Python\Python37\lib\site-packages\tensorflow\python\framework\dtypes.py:516: FutureWarning:

图论(A*算法,K短路) :POJ 2449 Remmarguts&#39; Date

Remmarguts' Date Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 25216   Accepted: 6882 Description "Good man never makes girls wait or breaks an appointment!" said the mandarin duck father. Softly touching his little ducks' head, h

关于图论的若干巴拉巴拉

最近课堂上正在讲图论 先安利MIT课程:http://open.163.com/special/opencourse/algorithms.html 因为本人对图论的概念并不是很清楚,所以还是整理一下吧. 1.图论的基本概念 几种常见的图的分类: 类型 边 允许多重边 允许环 简单图 无向 否 否 多重图 无向 是 否 伪图 无向 是 是 有向图 有向 否 是 有向多重图 有向 是 是 完全图:n个顶点上的完全图是在每对不同顶点之间都恰有一条边的简单图. 二分图:若把简单图G的顶点集合分为两个不

cdoj1580 简单图论问题

地址:http://acm.uestc.edu.cn/#/problem/show/1580 题目: 简单图论问题 Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) Submit Status 给出一个无向图,该图由nn个点和mm条边组成,每个点和每条边都有一个权值.对于该图的任意一个子图,我们定义A是该子图的点权和,B是该子图的边权和,C=A/b=AB是该子图的powerpow

SDUT 3361 数据结构实验之图论四:迷宫探索

数据结构实验之图论四:迷宫探索 Time Limit: 1000MS Memory Limit: 65536KB Submit Statistic Discuss Problem Description 有一个地下迷宫,它的通道都是直的,而通道所有交叉点(包括通道的端点)上都有一盏灯和一个开关:请问如何从某个起点开始在迷宫中点亮所有的灯并回到起点? Input 连续T组数据输入,每组数据第一行给出三个正整数,分别表示地下迷宫的结点数N(1 < N <= 1000).边数M(M <= 30

SDUT 2141 【TEST】数据结构实验图论一:基于邻接矩阵的广度优先搜索遍历

数据结构实验图论一:基于邻接矩阵的广度优先搜索遍历 Time Limit: 1000MS Memory Limit: 65536KB Submit Statistic Discuss Problem Description 给定一个无向连通图,顶点编号从0到n-1,用广度优先搜索(BFS)遍历,输出从某个顶点出发的遍历序列.(同一个结点的同层邻接点,节点编号小的优先遍历) Input 输入第一行为整数n(0< n <100),表示数据的组数.对于每组数据,第一行是三个整数k,m,t(0<

2017清北学堂集训笔记——图论

我们进入一个新的模块——图论! emmmmm这个专题更出来可能有点慢别介意,原因是要划的图和要给代码加的注释比较多,更重要的就是...这几个晚上我在追剧!!我们的少年时代超级超级超级好看,剧情很燃啊!!咳咳,好吧下面回归正题. 一.图的存储: 1.邻接矩阵: 假设有n个节点,建立一个n×n的矩阵,第i号节点能到达第j号节点就将[i][j]标记为1(有权值标记为权值), 样例如下图: 1 /*无向图,无权值*/ 2 int a[MAXN][MAXN];//邻接矩阵 3 int x,y;//两座城市

洛谷P3385 【模板】负环 DFS-SPFA 判负环 图论

洛谷P3385 [模板]负环 图论 今天get了 一个 DFS-SPFA 判负环的方法 一般的 BFS-SPFA 判负环 一般就是 不停地做,如果某点第 n+1次加入队列中,那么说明这个图存在负环然而我并不会证明,期望复杂度是 O(kM) k 大约是在 2 左右 但是其实对于一些极限数据,最坏可以把他卡到 O( NM) 额,这就直接炸飞了是不是,而且据说,一些数据比较强的题目,总会想到卡一卡SPFA的, 然后我们换一种思路 因为题目中一定存在一种 负环对吧,所以说假如你某段路径权值和为自然数的时

【转】彻底弄懂最短路径问题(图论)

来源:彻底弄懂最短路径问题 http://www.cnblogs.com/hxsyl/p/3270401.html P.S.根据个人需要,我删改了不少 问题引入 问题:从某顶点出发,沿图的边到达另一顶点所经过的路径中,各边上权值之和最小的一条路径——最短路径.解决最短路的问题有以下算法,Dijkstra算法,Bellman-Ford算法,Floyd算法和SPFA算法,另外还有著名的启发式搜索算法A*,不过A*准备单独出一篇,其中Floyd算法可以求解任意两点间的最短路径的长度.笔者认为任意一个最