• *模板--图论



    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
  • 相关阅读:
    .NET Core CSharp初级篇 1-1 基础类型介绍
    ASP.NET Core 基于JWT的认证(二)
    ASP.NET Core 基于JWT的认证(一)
    HOJ 1096 Divided Product (DFS)
    HDU1698 Just a Hook (区间更新)
    独立写作(A or B)
    HDU1394 Minimum Inversion Number(线段树OR归并排序)
    HDU5441 Travel (离线操作+并查集)
    学生管理系统(list)
    HDU5437 Alisha’s Party (优先队列 + 模拟)
  • 原文地址:https://www.cnblogs.com/yijiull/p/7224372.html
Copyright © 2020-2023  润新知