*模板--图论


dijkstra

 1 const int inf=0x3f3f3f3f;
 2 const int maxv=1010;
 3 const int maxe=1010;
 4 
 5 struct Edge
 6 {
 7     int u,v,w;
 8     int nex;
 9 }e[maxe<<1];
10 int head[maxv];
11 int cnt=0;
12 void init()
13 {
14     memset(head,-1,sizeof(head));
15     cnt=0;
16 }
17 void add(int u,int v,int w)
18 {
19     e[cnt].u=u;
20     e[cnt].v=v;
21     e[cnt].w=w;
22     e[cnt].nex=head[u];
23     head[u]=cnt++;
24 }
25 
26 typedef pair<int,int> PII;
27 int dis[maxv];
28 int par[maxv];
29 void dijkstra(int s)
30 {
31     priority_queue<PII,vector<PII>,greater<PII> > pq;
32     for(int i=0;i<maxv;i++) dis[i]=inf;
33     dis[s]=0;
34     pq.push(PII(0,s));
35     while(!pq.empty())
36     {
37         PII temp=pq.top();
38         pq.pop();
39         int u=temp.second;
40         if(dis[u]<temp.first) continue;
41         for(int i=head[u];i!=-1;i=e[i].nex)
42         {
43             if(dis[e[i].v]>dis[u]+e[i].w)
44             {
45                 dis[e[i].v]=dis[u]+e[i].w;
46                 par[e[i].v]=i;
47                 pq.push(PII(dis[e[i].v],e[i].v));
48             }
49         }
50     }
51 }
优先队列+前向星优化

bellman_ford

 1 const int inf=0x3f3f3f3f;
 2 const int maxv=1010;
 3 const int maxe=100010;
 4 int n,m;
 5 struct Edge
 6 {
 7     int u,v,w;
 8     int nex;
 9 }e[maxe<<1];
10 int head[maxv];
11 int cnt=0;
12 void init()
13 {
14     memset(head,-1,sizeof(head));
15     cnt=0;
16 }
17 void add(int u,int v,int w)
18 {
19     e[cnt].v=v;
20     e[cnt].w=w;
21     e[cnt].nex=head[u];
22     head[u]=cnt++;
23 }
24 int inq[maxv],deg[maxv],dis[maxv];
25 
26 bool bellman_ford()
27 {
28     queue<int> q;
29     memset(inq,0,sizeof(inq));
30     memset(deg,0,sizeof(deg));
31     for(int i=0;i<n;i++)
32     {
33         dis[i]=0;
34         inq[i]=1;
35         q.push(i);
36         deg[i]=1;
37     }
38     while(!q.empty())
39     {
40         int u=q.front();
41         q.pop();
42         inq[u]=0;
43         for(int i=head[u];i!=-1;i=e[i].nex)
44         {
45             int v=e[i].v;
46             if(dis[v]>dis[u]+e[i].w)
47             {
48                 dis[v]=dis[u]+e[i].w;
49                 if(!inq[v])
50                 {
51                     inq[v]=1;
52                     q.push(v);
53                     if(++deg[v]>=n) return 1;  //有负环  这块有点问题,不知道等号成不成立
54                 }
55             }
56         }
57     }
58     return 0;
59 }
最短路+判负环

Dinic

 1 struct Edge{
 2     int u, v, flow, cap, nxt;
 3     Edge(int u = 0, int v = 0, int cap = 0, int flow = 0, int nxt = 0) : u(u), v(v), cap(cap), flow(flow), nxt(nxt){}
 4 }e[maxe << 1];
 5 int head[maxv];
 6 int cnt;
 7 void init(){
 8     cnt = 0;
 9     memset(head, -1, sizeof(head));
10 }
11 void add(int u, int v, int cap){
12     e[cnt] = Edge(u, v, cap, 0, head[u]);
13     head[u] = cnt++;
14     e[cnt] = Edge(v, u, 0, 0, head[v]);
15     head[v] = cnt++;
16 }
17 int a[maxv];
18 char p[maxn][maxn];
19 int s, t, N;
20 int vis[maxv], d[maxv], cur[maxv];
21 int ans[maxn][maxn];
22 
23 int bfs(){
24     memset(vis, 0, sizeof(vis));
25     queue<int> q;
26     q.push(s);
27     vis[s] = 1;
28     d[s] = 0;
29     while(!q.empty()){
30         int u = q.front();
31         q.pop();
32         for(int i = head[u]; ~i; i = e[i].nxt){
33             int v = e[i].v;
34             if(!vis[v] && e[i].cap > e[i].flow){
35                 vis[v] = 1;
36                 d[v] = d[u] + 1;
37                 q.push(v);
38             }
39         }
40     }
41     return vis[t];
42 }
43 int dfs(int u, int a){
44     if(u == t || a == 0) return a;
45     int flow = 0, f;
46     for(int &i = cur[u]; ~i; i = e[i].nxt){
47         int v = e[i].v;
48         if(d[v] == d[u] + 1 && (f = dfs(v, min(a, e[i].cap - e[i].flow))) > 0){
49             e[i].flow += f;
50             e[i ^ 1].flow -= f;
51             flow += f;
52             a -= f;
53             if(a == 0) break;
54         }
55     }
56     return flow;
57 }
58 int Dinic(){
59     int flow = 0;
60     while(bfs()){
61         //for(int i = 0; i < N; i++) cur[i] = head[i];
62         memcpy(cur, head, sizeof head);
63         flow += dfs(s, inf);
64     }
65     return flow;
66 }
View Code

 

 ISPA

 1 struct Edge{
 2     int u, v, cap, flow, nxt;
 3     Edge(int u = 0, int v = 0, int cap = 0, int flow = 0, int nxt = 0) : u(u), v(v), cap(cap), flow(flow), nxt(nxt){}
 4 }e[maxe<<1];
 5 int head[maxv];
 6 int cnt;
 7 void init(){
 8     cnt = 0;
 9     memset(head, -1, sizeof(head));
10 }
11 void add(int u, int v, int cap){
12     e[cnt] = Edge(u, v, cap, 0, head[u]);
13     head[u] = cnt++;
14     e[cnt] = Edge(v, u, 0, 0, head[v]);
15     head[v] = cnt++;
16 }
17 int d[maxv], vis[maxv], num[maxv], cur[maxv], pre[maxv];
18 void bfs(){
19     queue<int> q;
20     memset(vis, 0, sizeof vis);
21     memset(d, -1, sizeof d);
22     vis[t] = 1;
23     d[t] = 0;
24     q.push(t);
25     while(!q.empty()){
26         int u = q.front();
27         q.pop();
28         for(int i = head[u]; ~i; i = e[i].nxt){
29             int id = i & (-2);
30             int v = e[id].u;
31             if(!vis[v] && e[id].cap > e[id].flow) {
32                 d[v] = d[u] + 1;
33                 vis[v] = 1;
34                 q.push(v);
35             }
36         }
37     }
38 }
39 int augment(){
40     int u = t, a = inf;
41     while(u != s){
42         int id = pre[u];
43         a = min(a, e[id].cap - e[id].flow);
44         u = e[id].u;
45     }
46     u = t;
47     while(u != s){
48         int id = pre[u];
49         e[id].flow += a;
50         e[id ^ 1].flow -= a;
51         u = e[id].u;
52     }
53     return a;
54 }
55 int ISAP(){
56     bfs();
57     int flow = 0;
58     memset(num, 0, sizeof num);
59     for(int i = 0; i < N; i++){
60         cur[i] = head[i];
61         if(~d[i]) num[d[i]]++;
62     }
63     int u = s;
64     while(d[s] < N){
65         if(u == t){
66             flow += augment();
67             u = s;
68         }
69         int ok = 0;
70         for(int i = cur[u]; ~i; i = e[i].nxt){
71             int v = e[i].v;
72             if(e[i].cap > e[i].flow && d[u] == d[v] + 1){
73                 ok = 1;
74                 pre[v] = i;
75                 cur[u] = i;
76                 u = v;
77                 break;
78             }
79         }
80         if(!ok){
81             int m = N - 1;
82             for(int i = head[u]; ~i; i = e[i].nxt){
83                 int v = e[i].v;
84                 if(e[i].cap > e[i].flow && ~d[v]) m = min(m, d[v]);
85             }
86             if(--num[d[u]] == 0) break;
87             num[d[u] = m + 1]++;
88             cur[u] = head[u];
89             if(u != s) u = e[pre[u]].u;
90         }
91     }
92     return flow;
93 }
View Code

 


求边双连通分量

(每个边双连通分量内部无桥)

 1 const int maxv=1010;
 2 struct Edge{
 3     int v,nex;
 4     bool iscut;
 5 }e[maxv<<2];
 6 int head[maxv];
 7 int cnt=0;
 8 void init(){
 9     memset(head,-1,sizeof(head));
10     cnt=0;
11 }
12 void add(int u,int v){
13     e[cnt].iscut=0;
14     e[cnt].v=v;
15     e[cnt].nex=head[u];
16     head[u]=cnt++;
17 }
18 
19 int pre[maxv];//  时间戳 
20 int bccno[maxv];// 标记该点属于的bcc
21 int dfsk,bcc_cnt;
22 bool vis[maxv];
23 
24 int dfs(int u,int id){
25     int lowu=pre[u]=++dfsk;
26     for(int i=head[u];i!=-1;i=e[i].nex){
27         int v=e[i].v;
28         if(i==(id^1)) continue;//// 反向边
29         if(!pre[v]){
30             int lowv=dfs(v,i);
31             lowu=min(lowv,lowu);
32             if(lowv>pre[u]) e[i].iscut=e[i^1].iscut=true;
33         }
34         else  lowu=min(lowu,pre[v]);
35     }
36     return lowu;
37 }
38 void dfs1(int u){
39     vis[u]=1;
40     bccno[u]=bcc_cnt;
41     for(int i=head[u];i!=-1;i=e[i].nex){
42         if(e[i].iscut) continue;
43         if(!vis[e[i].v]) dfs1(e[i].v);
44     }
45 }
46 //n个点,bcc_cnt个边双连通分量(从1开始)
47 //可以有重边
48 void find_bcc(int n){
49     memset(pre,0,sizeof(pre));
50     memset(bccno,0,sizeof(bccno));
51     memset(vis,0,sizeof(vis));
52     dfsk=bcc_cnt=0;
53     for(int i=0;i<n;i++) if(!pre[i]) dfs(i,-1);
54     for(int i=0;i<n;i++)
55         if(!vis[i]) bcc_cnt++,dfs1(i);
56 }
两遍dfs
 1 const int maxv = 25010;
 2 const int maxe = 50010;
 3 struct Edge{
 4     int v, nxt;
 5     bool iscut;
 6     Edge(){}
 7     Edge(int v, int nxt, bool iscut):v(v), nxt(nxt), iscut(iscut){}
 8 }e[maxe<<1];
 9 int head[maxv], cnt;
10 void init(){
11     memset(head, -1, sizeof head);
12     cnt = 0;
13 }
14 void add(int u, int v){
15     e[cnt] = Edge(v, head[u], 0);
16     head[u] = cnt++;
17     e[cnt] = Edge(u, head[v], 0);
18     head[v] = cnt++;
19 }
20 int n, m;
21 int pre[maxv], bccno[maxv];
22 bool vis[maxv];
23 int dfsk, bcc_cnt;
24 
25 int dfs1(int u, int id){
26     int lowu = pre[u] = ++dfsk;
27     for(int i = head[u]; ~i; i = e[i].nxt){
28         if(i == (id ^ 1)) continue;
29         int v = e[i].v;
30         if(!pre[v]){
31             int lowv = dfs1(v, i);  
32             lowu = min(lowu, lowv);
33             if(lowv > pre[u]) e[i].iscut = e[i ^ 1].iscut = 1;
34         }else {
35             lowu = min(lowu, pre[v]);
36         }
37     }
38     return lowu;
39 }
40 int dfs2(int u){
41     vis[u] = 1;
42     bccno[u] = bcc_cnt;
43     for(int i = head[u]; ~i; i = e[i].nxt){
44         if(e[i].iscut) continue;
45         if(!vis[e[i].v]) dfs2(e[i].v);
46     }
47 }
48 
49 void find_bcc(int n){
50     memset(pre, 0, sizeof pre);
51     memset(vis, 0, sizeof vis);
52     memset(bccno, 0, sizeof bccno);
53     dfsk = bcc_cnt = 0;
54     for(int i = 1; i <= n; i++) if(!pre[i]) dfs1(i, -1);
55     for(int i = 1; i <= n; i++) if(!vis[i]){
56         bcc_cnt++;
57         dfs2(i);
58     }
59 }
201803

求点双连通分量(注意求的是极大子图)

(每个点双连通分量内部无割顶)

 1 const int maxv=1010;
 2 const int maxe=1000010;
 3 int n,m;
 4 struct Edge{
 5     int u,v,nex;
 6 }e[maxe<<1];
 7 int head[maxv];
 8 int cnt=0;
 9 void add(int u,int v){
10     e[cnt].u=u;
11     e[cnt].v=v;
12     e[cnt].nex=head[u];
13     head[u]=cnt++;
14 }
15 void init(){
16     memset(head,-1,sizeof(head));
17     cnt=0;
18 }
19 
20 int pre[maxv];  //时间戳
21 int iscut[maxv]; //标记是否是割顶
22 int bccno[maxv]; //标记该点属于哪个连通分量
23 int dfsk,bcc_cnt;
24 vector<int> bcc[maxv];  //存连通分量里的点
25 stack<int> s;  //存边的标号
26 
27 int dfs(int u,int f){
28     int lowu=pre[u]=++dfsk;
29     int child=0;
30     for(int i=head[u];i!=-1;i=e[i].nex){
31         int v=e[i].v;
32         if(!pre[v]){
33             s.push(i);
34             child++;
35             int lowv=dfs(v,u);
36             lowu=min(lowu,lowv);
37             if(lowv>=pre[u]){
38                 iscut[u]=1;
39                 bcc_cnt++;
40                 bcc[bcc_cnt].clear(); //bcc从1开始编号
41                 for(;;){
42                     int te=s.top();
43                     s.pop();
44                     Edge p=e[te];
45                     if(bccno[p.u]!=bcc_cnt) {bcc[bcc_cnt].push_back(p.u);bccno[p.u]=bcc_cnt; }
46                     if(bccno[p.v]!=bcc_cnt) {bcc[bcc_cnt].push_back(p.v);bccno[p.v]=bcc_cnt; }
47                     if(p.u==u&&p.v==v) break;
48                 }
49             }
50         }else if(pre[v]<pre[u]&&v!=f){
51             s.push(i);
52             lowu=min(lowu,pre[v]);
53         }
54     }
55     if(f<0&&child==1) iscut[u]=0;
56     return lowu;
57 }
58 
59 void find_bcc(int n)
60 {
61     memset(pre,0,sizeof(pre));
62     memset(iscut,0,sizeof(iscut));
63     memset(bccno,0,sizeof(bccno));
64     dfsk=bcc_cnt=0;
65     for(int i=0;i<n;i++) if(!pre[i])
66         dfs(i,-1);
67 }
View Code

强连通分量

 1 const int maxv=10010;
 2 const int maxe=100010;
 3 int n,m;
 4 struct Edge{
 5     int v,nex;
 6 }e[maxe<<1];
 7 int head[maxv];
 8 int cnt=0;
 9 void init(){
10     memset(head,-1,sizeof(head));
11     cnt=0;
12 }
13 void add(int u,int v){
14     e[cnt].v=v;
15     e[cnt].nex=head[u];
16     head[u]=cnt++;
17 }
18 int pre[maxv]; //时间戳
19 int low[maxv]; 
20 int sccno[maxv];  //标记属于哪个强连通分量
21 int dfsk,scc_cnt;  //scc_cnt是强连通分量个数,从1到scc_cnt
22 stack<int> s;
23 
24 void dfs(int u){
25     pre[u]=low[u]=++dfsk;
26     s.push(u);
27     for(int i=head[u];i!=-1;i=e[i].nex){
28         int v=e[i].v;
29         if(!pre[v]){
30             dfs(v);
31             low[u]=min(low[u],low[v]);
32         }
33         else if(!sccno[v]) //还在栈里!
34             low[u]=min(low[u],low[v]);
35     }
36     if(pre[u]==low[u]){
37         scc_cnt++;
38         for(;;){
39             int x=s.top();
40             s.pop();
41             sccno[x]=scc_cnt;
42             if(x==u) break;
43         }
44     }
45 }
46 void find_scc(int n){
47     memset(pre,0,sizeof(pre));
48     memset(low,0,sizeof(low));
49     memset(sccno,0,sizeof(sccno));
50     dfsk=scc_cnt=0;
51     for(int i=0;i<n;i++) if(!pre[i]) dfs(i);
52 }
View Code

TwoSat

 1 struct TwoSAT
 2 {
 3     int n;
 4     vector<int> G[maxn<<1];
 5     bool mark[maxn<<1];
 6     int s[maxn<<1],c;
 7 
 8     bool dfs(int x)
 9     {
10         if(mark[x^1]) return false;
11         if(mark[x]) return true;
12         mark[x]=true;
13         s[c++]=x;
14         for(int i=0;i<G[x].size();i++)
15             if(!dfs(G[x][i])) return false;
16         return true;
17     }
18 
19     void init(int n)
20     {
21         this->n=n;
22         for(int i=0;i<n*2;i++) G[i].clear();
23         memset(mark,0,sizeof(mark));
24     }
25 
26     void add_clause(int x,int xv,int y,int yv)
27     {
28         x=x*2+xv;
29         y=y*2+yv;
30         G[x^1].push_back(y);
31         G[y^1].push_back(x);
32     }
33 
34     bool solve()
35     {
36         for(int i=0;i<n*2;i+=2)
37             if(!mark[i]&&!mark[i^1])
38             {
39                 c=0;
40                 if(!dfs(i))
41                 {
42                     while(c>0) mark[s[--c]]=false;
43                     if(!dfs(i+1)) return false;
44                 }
45             }
46         return true;
47     }
48 }solver;
View Code

朱刘算法

 1 struct Edge{
 2     int u, v, w;
 3     Edge(int u = 0, int v = 0, int w = 0) : u(u), v(v), w(w) {}
 4 }e[maxe];
 5 
 6 int  pre[maxn], id[maxn], vis[maxn];
 7 LL in[maxn];
 8 /*
 9  * n个点(标号1到n)(有时要添加虚拟节点0)
10  * m条边(0到m-1)
11  */
12  LL Dir_MST(int n, int m){
13     int rt = 0;
14     LL ans = 0;
15     for(int i = 1; i <= n; i++)  e[m++] = Edge(rt, i, 0);  //添加虚拟节点rt = 0
16     n++;
17     int cnt = m;
18     while(true) {
19         //找最小入边
20         for(int i = 0; i < n; i++) in[i] = inf;
21         for(int i = 0; i < cnt; i++) {
22             int u = e[i].u, v = e[i].v, w = e[i].w;
23             if(w < in[v] && u != v) {
24                 in[v] = w;
25                 pre[v] = u;
26             }
27         }
28         for(int i = 0; i < n; i++){
29             if(i == rt) continue;
30             if(in[i] == inf)    return -1; // 有点没有入边,无法到达
31         }
32         //找环
33         int cntnode = 0;
34         memset(vis, -1, sizeof(vis));
35         memset(id, -1, sizeof(id));
36         in[rt] = 0;
37         for(int i = 0; i < n; i++){  //标记每个环
38             ans = ans + in[i];
39             int v = i;
40             while(vis[v] != i && v != rt && id[v] == -1) { //每个点寻找其前序点,要么最终寻找至根部,要么找到一个环
41                 vis[v] = i;
42                 v = pre[v];
43             }
44             if(id[v] == -1 && v != rt){  //缩点
45                 for(int u = pre[v]; u != v; u = pre[u]) id[u] = cntnode;
46                 id[v] = cntnode++;
47             }
48         }
49         if(cntnode == 0) break;  //无环   则break
50 
51         //建立新图
52         for(int i = 0; i < n; i++){
53             if(id[i] == -1) id[i] = cntnode++;
54         }
55         for(int i = 0; i < cnt; i++){
56             int v = e[i].v;
57             e[i].u = id[e[i].u];
58             e[i].v = id[e[i].v];
59             if(e[i].u != e[i].v) e[i].w -= in[v];
60         }
61         n = cntnode;
62         rt = id[rt];
63     }
64     return ans;
65 }
View Code
原文地址:https://www.cnblogs.com/yijiull/p/7224372.html