图论模板简单整理

唔,图论部分暂时就看到这里了,整理一下最近学的东西

//最短路
//dijkstra
void dijkstra() {
    memset(vis,0,sizeof(vis));
    for(int i = 1;i <= n;i++) {
        d[i] = -1;
    }
    d[n] = 1;
    for(int k = 1;k <= n;k++) {
        double maxv = -1; int x = n;
        for(int i = 1;i <= n;i++) if(!vis[i] && d[i] > maxv) {
            maxv = d[x = i];
        }
        vis[x] = true;
        for(int i = 1;i <= n;i++) if(!vis[i] && p[x][i] >= 0) {
            if(d[i] == -1) d[i] = d[x] * p[x][i];
            else d[i] = max(d[i],d[x] * p[x][i]);
        }
    }
}

//dijkstra + heap

void dijkstra(int *v) {
    memset(vis,0,sizeof(vis));
    for(int i = 1;i <= n;i++) d[i] = INF;
    d[1] = 0;
    priority_queue<Node> q;
    q.push(Node(d[1],1));
    while(!q.empty()) {
        Node now = q.top(); q.pop();
        int x = now.b;
        if(vis[x]) continue;
        vis[x] = true;
        for(int i = first[x];i != 0;i = nxt[i]) {
            if(d[v[i]] > d[x] + w[i]) {
                d[v[i]] = d[x] + w[i];
                q.push(Node(d[v[i]],v[i]));
            }
        }
    }
}

//bellman-ford
void bellman_ford() {
    for(int i = 0;i < M;i++) d[i] = INF;
    d[0] = 0;
    for(int i = 0;i < M;i++) {
        for(int j = 0;j < M;j++) {
            for(int k = 0;k < M;k++) if(dist[j][k] < INF) {
                if(d[j] < INF) {
                    d[k] = min(d[k],d[j] + dist[j][k]);
                }
            }
        }
    }
    printf("%.2f\n",d[M - 1]);
}

//SPFA
void spfa(int *v,int *d) {
    memset(vis,0,sizeof(vis));
    for(int i = 1;i <= N;i++) d[i] = INF;
    d[X] = 0;
    queue<int> q;
    q.push(X);
    while(!q.empty()) {
        int u = q.front(); q.pop();
        vis[u] = false;
        for(int i = first[u];i != 0;i = nxt[i]) {
            if(d[v[i]] > d[u] + w[i]) {
                d[v[i]] = d[u] + w[i];
                if(!vis[v[i]]) {
                    vis[v[i]] = true;
                    q.push(v[i]);
                }
            }
        }
    }
}

//欧拉路和欧拉回路
//寻找欧拉路并且输出路径
void dfs(int now) {
    for(int i = 0;i < e[now].size();i++) {
        if(e[now][i].vis == 0) {
            e[now][i].vis = 1;
            dfs(e[now][i].v);
            ans.push(e[now][i].str);
        }
    }
}

//网络流
//标号法
//Ford-Fulkerson
void solve() {
    memset(flow,0,sizeof(flow));
    alpha[s] = INF;
    while(1) {
        //初始化标号
        for(int i = 1;i <= t;i++) pre[i] = -2;
        pre[s] = -1;
        //初始化队列,源点入列
        qs = 0; qe = 1;
        q[qs] = s;
        //标号过程
        while(qs < qe && pre[t] == -2) {    //终点没有被标号并且队列非空
            int v = q[qs]; qs++;
            //printf("now v is %d\n",v);
            for(int i = 1;i <= t;i++) {
                //如果目标点没有被标号并且还有残余流量
                if(pre[i] == -2 && dist[v][i] - flow[v][i] != 0) {
                    pre[i] = v;
                    alpha[i] = min(alpha[v],dist[v][i] - flow[v][i]);
                    q[qe++] = i;
                }
            }
        }
        //没有找到到汇点的增广路,退出
        if(pre[t] == -2) {
            break;
        }
        //逆向更新
        int aval = alpha[t];
        for(int i = t;pre[i] != -1;i = pre[i]) {
            flow[pre[i]][i] += aval;
            flow[i][pre[i]] = -flow[pre[i]][i];
        }
    }
    //统计流量
    int ans = 0;
    for(int i = 1;i <= n;i++) {
        ans += flow[i][t];
    }
    printf("%d\n",ans);
}

//dinic

bool bfs() {
    qs = qe = 0;
    q[qe++] = s;
    memset(level,0,sizeof(level));
    level[s] = 1;
    while(qs < qe) {
        int v = q[qs++];
        if(v == t) break;
        for(int i = s;i <= t;i++) if(cap[v][i] && !level[i]) {
            level[i] = level[v] + 1;
            q[qe++] = i;
        }
    }
    return level[t];
}

int dfs(int now,int alpha) {
    int sum = 0;
    if(now == t) return alpha;
    for(int i = s;i <= t;i++) {
        if(level[i] == level[now] + 1 && alpha && cap[now][i]) {
            int ret = dfs(i,min(alpha,cap[now][i]));
            cap[now][i] -= ret;
            cap[i][now] += ret;
            alpha -= ret;
            sum += ret;
        }
    }
    return sum;
}

void dinic() {
    int ans = 0;
    while(bfs()) ans += dfs(s,INT_MAX);
    printf("%d\n",ans);
}

//混合图欧拉回路的判断
//先把所有的边看成是有向边,判断所有的点入度和出度之差是否是偶数,如果有奇数出现那么就不是欧拉回路。
//然后去掉图中所有的有向边,建立虚拟的源点和汇点,如果剩下的点中有入度大于出度的,就建立到汇点的边,容量为入度出度之差/2,如果有出度大于入读的,就建立到源点的边,容量同样为入度和出度之差的一半,做一遍最大流,流量和要调换的边的数量相等。
//满流的边需要调换

using namespace std;

typedef long long LL;
const int maxn = 205;
const int INF = INT_MAX / 3;

struct Edge {
    int u,v,cap;
    Edge(int u,int v,int cap):u(u),v(v),cap(cap) {}
};

int n,m,incnt[maxn],outcnt[maxn];
int deg[maxn],s,t;
vector<Edge> edges;
vector<int> e[maxn];

void adde(int u,int v,int w) {
    int m = edges.size();
    edges.push_back(Edge(u,v,w));
    edges.push_back(Edge(v,u,0));
    e[u].push_back(m);
    e[v].push_back(m ^ 1);
}

int level[maxn],q[maxn * 2],qs,qe;
bool bfs() {
    //建立层次网络
    memset(level,0,sizeof(level));
    level[s] = 1;
    qs = qe = 0;
    q[qe++] = s;
    while(qs < qe) {
        int now = q[qs++],nm = e[now].size();
        if(now == t) break;
        for(int i = 0;i < nm;i++) {
            Edge &ne = edges[e[now][i]];
            if(ne.cap && level[ne.v] == 0) {
                level[ne.v] = level[now] + 1;
                q[qe++] = ne.v;
            }
        }
    }
    return level[t];
}

int dfs(int now,int alpha) {
    if(now == t) return alpha;
    int sum = 0,nm = e[now].size();
    for(int i = 0;i < nm;i++) {
        Edge &ne = edges[e[now][i]];
        if(level[now] + 1 == level[ne.v] && ne.cap && alpha) {
            int ret = dfs(ne.v,min(alpha,ne.cap));
            ne.cap -= ret; edges[e[now][i] ^ 1].cap += ret;
            sum += ret; alpha -= ret;
        }
    }
    if(sum == 0) level[now] = -1;
    return sum;
}

void dinic() {
    while(bfs()) dfs(s,INF);
}

bool solve() {
    s = 0; t = n + 1;
    //判断入度出度之差是否为偶数
    for(int i = 1;i <= n;i++) {
        deg[i] = incnt[i] - outcnt[i];
        if(deg[i] & 1) return false;
    }
    //建立容量网络
    for(int i = 1;i <= n;i++) {
        //如果入度小于出度,建立从起点到这个点的边,容量为deg/2
        if(deg[i] < 0) adde(s,i,-deg[i] / 2);
        //如果出度大于入读,建立从当前点到汇点的边,容量同样为deg/2
        if(deg[i] > 0) adde(i,t,deg[i] / 2);
    }
    //计算最大流
    dinic();
    //判断从源点出发的所有边是否满流
    int m = e[s].size();
    for(int i = 0;i < m;i++) {
        if(edges[e[s][i]].cap != 0) return false;
    }
    return true;
}

int main() {
    int T; scanf("%d",&T);
    while(T--) {
        scanf("%d%d",&n,&m);
        edges.clear();
        for(int i = 0;i <= n + 1;i++) e[i].clear();
        memset(incnt,0,sizeof(incnt));
        memset(outcnt,0,sizeof(outcnt));
        for(int i = 1;i <= m;i++) {
            int u,v,c; scanf("%d%d%d",&u,&v,&c);
            //先将无向边全部作为有向边处理
            incnt[v]++; outcnt[u]++;
            //无向边存起来
            if(c == 0) adde(u,v,1);
        }
        if(solve()) puts("possible");
        else puts("impossible");
    }
    return 0;
}

//求最小割是否唯一
//判断方法是先做一遍最大流求最小割,然后从源点和汇点分别遍历所有能够到达的点,看是否覆盖了所有的点,如果覆盖了所有的点,那就是唯一的,否则就是不唯一的。

void solve() {
    //先做一遍最大流
    while(bfs()) dfs(s,INF);
    //分别从起点和终点做一遍bfs
    memset(vis,0,sizeof(vis));
    qs = qe = 0;
    q[qe++] = s;
    vis[s] = true;
    while(qs < qe) {
        int now = q[qs++];
        for(int i = first[now];~i;i = nxt[i]) {
            if(cap[i] && !vis[v[i]]) {
                vis[v[i]] = true; q[qe++] = v[i];
            }
        }
    }
    qs = qe = 0;
    q[qe++] = t;
    vis[t] = true;
    while(qs < qe) {
        int now = q[qs++];
        for(int i = first[now];~i;i = nxt[i]) {
            if(cap[i ^ 1] && !vis[v[i]]) {
                vis[v[i]] = true; q[qe++] = v[i];
            }
        }
    }
    for(int i = 1;i <= n;i++) {
        if(!vis[i]) {
            puts("AMBIGUOUS");
            return;
        }
    }
    puts("UNIQUE");
}

//带容量限制的无源点和汇点的网络流
//建立虚拟的源点和汇点,因为忽略掉了容量下界之后会导致流量不平衡,所以对于每个u,v,u多出来的流量流到汇点,v不够的流量从源点补流

typedef long long LL;
const int maxn = 205;
const int maxm = maxn * maxn;
const int INF = INT_MAX / 3;
int cap[maxn][maxn],flow[maxn][maxn],low[maxm];
int q[maxn],alpha[maxn],pre[maxn];
int uu[maxm],vv[maxm];
int n,m,s,t,qs,qe;

void solve() {
    memset(flow,0,sizeof(flow));
    while(1) {
        qs = qe = 0;
        for(int i = s;i <= t;i++) pre[i] = -2;
        pre[s] = -1; alpha[s] = INF;
        q[qe++] = s;
        while(qs < qe) {
            int now = q[qs++];
            for(int i = s;i <= t;i++) {
                if(cap[now][i] - flow[now][i] != 0 && pre[i] == -2) {
                    q[qe++] = i;
                    pre[i] = now;
                    alpha[i] = min(alpha[now],cap[now][i] - flow[now][i]);
                }
            }
        }
        if(pre[t] == -2) break;
        for(int i = t;pre[i] != -1;i = pre[i]) {
            flow[pre[i]][i] += alpha[t];
            flow[i][pre[i]] -= alpha[t];
        }
    }
    bool ok = true;
    for(int i = s + 1;i <= t;i++) {
        if(cap[s][i] - flow[s][i]) ok = false;
    }
    for(int i = s;i < t;i++) if(cap[i][t] - flow[i][t]) ok = false;
    if(!ok) puts("NO");
    else {
        puts("YES");
        for(int i = 0;i < m;i++) {
            printf("%d\n",flow[uu[i]][vv[i]] + low[i]);
        }
    }
}

int main() {
    scanf("%d%d",&n,&m);
    s = 0; t = n + 1;
    memset(cap,0,sizeof(cap));
    for(int i = 0;i < m;i++) {
        int u,v,l,c; scanf("%d%d%d%d",&u,&v,&l,&c);
        low[i] = l;
        cap[u][v] += c - l;
        cap[s][v] += l;
        cap[u][t] += l;
        uu[i] = u; vv[i] = v;
    }
    solve();
    return 0;
}

//二分图最大匹配
int dfs(int now) {
    for(int i = 1;i <= cnty;i++) if(g[now][i] && !vis[i]) {
        vis[i] = true;
        if(!by[i] || dfs(by[i])) {
            bx[now] = i; by[i] = now;
            return 1;
        }
    }
    return 0;
}

int solve() {
    int ret = 0;
    memset(bx,0,sizeof(bx));
    memset(by,0,sizeof(by));
    for(int i = 1;i <= cntx;i++) if(!bx[i]) {
        memset(vis,0,sizeof(vis));
        ret += dfs(i);
    }
    return ret;
}

//最小点权覆盖->最小割+拆点
//求最大独立集 最大独立点集 = 点数 - 最大匹配数注意
//最小点覆盖 == 最大匹配
//最小路径覆盖 = 顶点数 - 最大匹配

  

图论模板简单整理

时间: 2024-10-11 15:17:49

图论模板简单整理的相关文章

图论模板

图论模板 LCA 离线 tarjan //可使用快读 #include <iostream> #include <cstdio> using namespace std; const int MAXN=500050; int po[MAXN],qs[MAXN],fa[MAXN],nume,numq,n,m,root,ans[MAXN]; bool f[MAXN]; struct edge{ int to,nxt; }e[2*MAXN]; struct ques{ int to,nx

PHP语言基础简单整理

1.开始结束标记<? ... ?> 2.定义变量:$变量名 例: $str="锦清笋";不需要指明数据类型 3.输出语句:(1)echo "hello world!";---echo命令(2)print();输出语句,是函数,有返回值.输出成功返回1,失败返回0.(3) printf();格式化输出字符串.例:printf("%d,%f",12,12.3); (4)sprintf();格式化拼接字符串,不是输出语句,只能将字符串拼接.

关于数字证书理解的简单整理以及12306网站证书简单分析

首先简单理解一下什么是数字证书.这里是一篇英文文档,描述的很形象.形象的描述了什么是公钥,什么是私钥,如果确保数字证书的可靠性等. 下面,我们看一个应用"数字证书"的实例:https协议.这个协议主要用于网页加密. 一般我们电脑的浏览器中都有一些受信任的证书颁发机构列表, 里边存储的都是一些机构的信息.这些机构都是权威的.当然可以通过安装软件的方式,来增加证书颁发机构,比如中国银行的根证书软件,阿里巴巴的根证书软件.默认我们认为这些软件都是从官网下载的,是绝对的没被篡改的,可靠的.简单

哈希综述的简单整理

刚接触哈希,由于之后有其他工作,所以时间比较紧,只是做了一个简单粗糙的整理,可能还有不少错误.自己先放着,以后如果需要用到hash了在回头重新整理. 哈希综述的简单整理.pdf

ectouch第四讲之 ECshop模板机制整理

网上的资源感觉还是有些用,可以看看,帮助理解, ECshop模板机制整理 原文:http://blog.sina.com.cn/s/blog_6900af430100nkn8.html 数据处理: ECshop根目录下及admin目录下的文件是对应前台.后台页面的数据处理页,在这些文件中对页面所要展示的内容进行处理,之后通过smarty的assign()方法注册变量,最后通过display()方法加载相应的模板文件.但这里我们需要注意ECshop单独封装的几个方法,用于处理模板的公共内容及页面中

MYBATIS 简单整理与回顾

这两天简单整理了一下MyBatis 相关api和jar包这里提供一个下载地址,免得找了 链接:http://pan.baidu.com/s/1jIl1KaE 密码:d2yl A.简单搭建跑项目 2.进行相关xml配置 放在根目录下 3.配置数据库映射文件 这里给个例子文件 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD

图论的简单知识结构

本文出自:Svitter的Blog 以及 Github 图论Graph 8/8/2014 9:23:16 AM 图的基本概念 图的定义 Defination 图是由顶点集合(Vertex)及顶点间的关系集合(边Edge)组成的一种数据结构: > Graph=( V, E ) 顶点Vertex V = {x | x ∈ 某个数据对象} 边的集合Edge E = {(x, y) | x,y ∈ V } E = {(x, y) | x, y ∈ V && path(x,y) Path(x,

phpcms模板标签整理

{template "content","header"} 调用根目录下phpcms\template\content\header文件 {CHARSET} 字符集 (gbk或者utf-8) {if isset($SEO['title']) && !empty($SEO['title'])} {$SEO['title']}{/if} {$SEO['site_title']} {$SEO['keyword']} {$SEO['description']

图论模板——最大流及费用流模板

图论模板--最大流及费用流模板 最大流--SAP 时间复杂度:O(v^2*e) const int MAXN=1010;//点数的最大值 const int MAXM=1010;//边数的最大值 const int INF=0x3f3f3f3f; struct Node { int from,to,next; int cap; }edge[MAXM]; int tol; int head[MAXN]; int dep[MAXN]; int gap[MAXN];//gap[x]=y :说明残留网络