1.顺序创建图,删除

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include <iostream>
#include <cstring>
using namespace std;
const int N = 20010;
int n, m;
int h[N], e[N], ne[N], w[N], idx=0;

void add(int a, int b, int c)
{
e[idx] = b, w[idx] = c;
if (h[a] == -1 || b < e[h[a]])
ne[idx] = h[a], h[a] = idx++;
else
{
int t = h[a], pre = h[a];
while (b > e[t] && t != -1)
pre = t, t = ne[t];
ne[idx] = t, ne[pre] = idx++;
}
}
void Del(int a,int b)
{
if (e[h[a]] == b)
{
h[a] = ne[h[a]];
}
else
{
int t = h[a];
int pre = t;
while (e[t] != b)
pre = t, t = ne[t];
ne[pre] = ne[t];
}

}
int main()
{
memset(h, -1, sizeof h);
cin >> n >> m;
for (int i = 0; i < m; i++)
{
int a, b, c;
cin >> a >> b >> c;
add(a, b, c);
}
int k;
cin >> k;
for (int i = 0; i < k; i++)
{
int a, b;
cin >> a >> b;
Del(a, b);
}
for (int i = 0; i < n; i++)
{
if (h[i] == -1) continue;
printf("%d:", i);
for (int j = h[i]; j != -1; j = ne[j])
{
int k = e[j];
printf("(%d,%d,%d)", i, k, w[j]);
}
cout << endl;
}
}

2.dfs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <iostream>
#include <cstring>
using namespace std;
const int N = 20010;
int h[N], e[N], ne[N], idx;
int n, m;
int st[N];
void add(int a, int b)
{
e[idx] = b;
if (h[a] == -1 || b < e[h[a]])
ne[idx] = h[a], h[a] = idx++;
else
{
int t = h[a], pre = h[a];
while (b > e[t] && t != -1)
pre = t, t = ne[t];
ne[idx] = t, ne[pre] = idx++;
}
}

void dfs(int u)
{
st[u] = 1;
cout << u <<" ";
for (int i = h[u]; i != -1; i = ne[i])
{
int j = e[i];
if (!st[j])
{
dfs(j);
}
}
}
int main()
{
cin >> n >> m;
memset(h, -1,sizeof h);
for (int i = 0; i < m; i++)
{
int a, b;
cin >> a >> b;
add(a, b);
}
for (int i = 0; i < n; i++)
if (!st[i])
dfs(i);
}

3.字典序最小

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#include <iostream>
#include <stack>
#include <queue>
using namespace std;

const int N = 2e5 + 10;
const int INF = 0x3f3f3f3f;

struct Edge {
int veradj;
int cost;
Edge* link;
};
struct Vertex {
int vername;
Edge* adjacent;
};

Vertex Head[N];

void CreateGraph(int n,int e)
{
for(int i=0;i<n;i++)
{
Head[i].vername=i;
Head[i].adjacent=NULL;
}
for(int i=0;i<e;i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
Edge* t=new Edge;
t->veradj=b,t->cost=c,t->link=NULL;
if(Head[a].adjacent==NULL) Head[a].adjacent=t;
else
{
Edge* p=Head[a].adjacent;
Edge* pre=NULL;
if(b<p->veradj)
{
t->link=p;
Head[a].adjacent=t;
}
else
{
while(p!=NULL&&b>p->veradj)
{
pre=p;
p=p->link;
}
t->link=p;
pre->link=t;
}

}
}
}

int findMin(int S[], int dist[], int n, priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>>& pq) {
while (!pq.empty()) {
int v = pq.top().second;
pq.pop();
if (S[v] == 0) {
return v;
}
}
return -1;
}

void Dijkstra(Vertex Head[], int n, int u, int dist[], int pre[], int minlen[]) {
int S[N] = {0};
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;

for (int i = 0; i < n; i++) {
pre[i] = -1;
dist[i] = INF;
minlen[i] = INF;
}

dist[u] = 0;
minlen[u] = 1;
pq.push({0, u}); // 将起始节点加入 priority_queue

while (!pq.empty()) {
int v = findMin(S, dist, n, pq);
if (v == -1)
break;

S[v] = 1;
for (Edge* p = Head[v].adjacent; p != NULL; p = p->link) {
int w = p->veradj;
if (S[w] == 0 && dist[v] + p->cost < dist[w]) {
dist[w] = dist[v] + p->cost;
pre[w] = v;
minlen[w] = minlen[v] + 1;
pq.push({dist[w], w}); // 更新距离后将新节点加入 priority_queue
} else if (S[w] == 0 && dist[v] + p->cost == dist[w] && minlen[v] + 1 < minlen[w]) {
minlen[w] = minlen[v] + 1;
pre[w] = v;
} else if (S[w] == 0 && dist[v] + p->cost == dist[w] && minlen[v] + 1 == minlen[w]) {
int a = v, b = pre[w];
while (pre[a] != pre[b]) {
a = pre[a];
b = pre[b];
}
if (a < b)
pre[w] = v;
}
}
}
}

void findPath(int pre[], int v) {
stack<int> path;
while (v != -1) {
path.push(v);
v = pre[v];
}
while (!path.empty()) {
cout << path.top();
path.pop();
if (!path.empty())
cout << "->";
}
cout << endl;
}

int main() {
int n, e;
cin >> n >> e;
CreateGraph(n, e);

int dist[N], pre[N], minlen[N];
Dijkstra(Head, n, 0, dist, pre, minlen);
for (int i = 1; i < n; i++) {
if (dist[i] != INF) {
findPath(pre, i);
}
}

return 0;
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#include <iostream>
#include <cstring>
#include <queue>
#include <stack>
using namespace std;
const int N = 20010;
const int INF = 0x3f3f3f3f;
int h[N], e[N], ne[N], w[N], idx;
int n, m;
int dist[N], st[N],pre[N],minlen[N];
typedef pair<int, int>PII;
void add(int a, int b, int c)
{
e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++;
}

void dijkstra()
{
memset(dist, INF, sizeof dist);
dist[0] = 0;
priority_queue<PII, vector<PII>, greater<PII>>pq;
pq.push({ 0,0 });
while (!pq.empty())
{
auto t = pq.top();
pq.pop();
int ver = t.second;
if (st[ver]) continue;

for (int i = h[ver]; i != -1; i = ne[i])
{
int j = e[i];
if (!st[j] && dist[j] > dist[ver] + w[i])
{
dist[j] = dist[ver] + w[i];
minlen[j] = minlen[ver] + 1;
pre[j] = ver;
pq.push({ dist[j],j });
}
else if (!st[j] && dist[j] == dist[ver] + w[i] && minlen[ver] + 1 < minlen[j])
{
minlen[j] = minlen[ver] + 1;
pre[j] = ver;
}
else if (!st[j] && dist[j] == dist[ver] + w[i] && minlen[j] == minlen[ver] + 1)
{
int a = ver, b = pre[j];
while (pre[a] != pre[b])
{
a = pre[a];
b = pre[b];
}
if (a < b)
pre[j] = ver;
}
}
}
}
void findpath(int u)
{
stack<int>s;
while (u != -1)
{
s.push(u);
u = pre[u];
}
while (!s.empty())
{
cout << s.top();
s.pop();
if (!s.empty())
cout << "->";
}
cout << endl;
}
int main()
{
cin >> n >> m;
memset(h, -1,sizeof h);
for (int i = 0; i < m; i++)
{
int a, b, c;
cin >> a >> b >> c;
add(a, b, c);
}
pre[0] = -1;
dijkstra();
for (int i = 1; i < n; i++)
{
findpath(i);
}
}