图论模板自存c++

树的重心/深搜
图中点的层次/宽搜
有向图的拓扑排序
Dijkstra求最短路
bellman-ford
spfa求最短路
spfa判负环
floyd求最短路
prim求最小生成树
kruskal求最小生成树
判定二分图
匈牙利算法/二分图的最大匹配

树的重心/深搜

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
int n;

struct node{
    int to,next;
}edge[N*2];
int head[2*N];
int cnt;
bool vis[N];

void add(int u,int v)
{
    edge[++cnt] = {v,head[u]};
    head[u] = cnt;
}
int ans= N;
int dfs(int u)
{
    int res = 0,sum = 1;
    vis[u] = 1;
    
    for(int i = head[u];i;i=edge[i].next)
    {
        int to = edge[i].to;
        if(vis[to] == 0)
        {
            int s = dfs(to);
            res = max(res, s);
            sum += s;
        }
        
    }
    res = max(res , n - sum);
    ans = min(ans, res);
    
    return sum;
}

int main()
{
    cin>>n;
    for(int i = 1;i < n;i++)
    {
        int u,v;
        cin>>u>>v;
        add(u , v);
        add(v , u);
    }
    dfs(1);
    cout<<ans<<"\n";
    
    return 0;
}

图中点的层次/宽搜

#include <bits/stdc++.h>
using namespace std;

const int N = 1e5+5;
struct node{
    int to,next;
}edge[N];
int head[N];
int cnt;
int n,m;
int dist[N];
bool vis[N];

void add(int u,int v)
{
    edge[++cnt]={v,head[u]};
    head[u] = cnt;
}

priority_queue<pair<int,int> > q;

int dfs()
{
    memset(dist,0x3f,sizeof dist);
    q.push({0,1});
    dist[1] = 0;
    while(!q.empty())
    {
        int now = q.top().second;
        q.pop();
        if(vis[now] == 1) continue;
        vis[now] = 1;
        if(now == n)
        {
            return dist[now];
        }
        for(int i = head[now];i;i=edge[i].next)
        {
            int to=edge[i].to;
            if(dist[to] > dist[now] + 1)
            {
                dist[to] = dist[now] + 1;
                q.push({-1*dist[to],to});
            }
        }
    }
    
    return -1;
}

int main()
{
    cin>>n>>m;
    for(int i = 1;i <= m;i++)
    {
        int u,v;
        cin>>u>>v;
        add(u,v);
    }
    
    cout<<dfs();
    
    return 0;
}

有向图的拓扑序列

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5+5;
int m,n;
vector<int>e[N],tp;
int d[N];

queue<int>q;

int toposort()
{
    for(int i = 1;i <= n;i++)
        if(d[i] == 0) q.push(i);
    
    while(!q.empty())
    {
        int now = q.front();
        q.pop();
        tp.push_back(now);
        for(auto i : e[now])
        {
            if(--d[i] == 0) q.push(i);
        }
    }
    return (tp.size() == n);
    
}


int main()
{
    cin>>n>>m;
    for(int i = 1;i <= m;i++)
    {
        int u,v;
        cin>>u>>v;
        d[v]++;
        e[u].push_back(v);
    }
    bool f = toposort();
    if(f == 0) cout<<-1<<"\n";
    else
    {
        for(auto i : tp)
        {
            cout<<i<<" ";
        }
    }
    
    return 0;
}

Dijkstra求最短路

#include <bits/stdc++.h>
using namespace std;
const int N = 150005;
int n,m;
struct node{
    int to,w,next;
}edge[N];
int head[N];
int cnt;

void add(int u,int v,int w)
{
    edge[++cnt] = {v,w,head[u]};
    head[u] = cnt;
}
int dist[N];
bool vis[N];
priority_queue<pair<int ,int > > q;

void dijkstra()
{
    memset(dist,0x3f,sizeof dist);
    q.push({0,1});
    dist[1] = 0;
    
    while(!q.empty())
    {
        int now = q.top().second;
        q.pop();
        if(vis[now] == 1) continue;
        vis[now] = 1;
        for(int i = head[now];i;i=edge[i].next)
        {
            int to = edge[i].to;
            int w = edge[i].w;
            if(dist[to] > dist[now] + w)
            {
                dist[to] = dist[now] + w;
                q.push({-1*dist[to],to});
            }
        }
    }
    if(dist[n] >= 0x3f3f3f3f) cout<<"-1"<<"\n";
    else cout<<dist[n]<<"\n";
    return;
    
}

int main()
{
    cin>>n>>m;
    for(int i = 1;i <= m;i++)
    {
        int u,v,w;
        cin>>u>>v>>w;
        add(u,v,w);
    }
    dijkstra();
    
    return 0;
}

bellman-ford

#include <bits/stdc++.h>
using namespace std;

struct node{
    int u,v,w;
}edge[10005];
int n,m,k;
int dist[505];
int dist2[505];
void bellman()
{
    memset(dist,0x3f,sizeof dist);
    dist[1]=0;
    for(int i = 0;i < k;i++)
    {
        memcpy(dist2,dist,sizeof dist);
        for(int j = 1;j <= m;j++)
        {
            int u = edge[j].u;
            int v = edge[j].v;
            int w = edge[j].w;
            dist[v] = min(dist2[u]+w,dist[v]);
            
        }
    }
    
    if(dist[n] >= 0x3f3f3f3f/2) cout<<"impossible"<<"\n";
    else cout<<dist[n]<<"\n";
}

int main()
{
    cin>>n>>m>>k;
    for(int i = 1;i <= m;i++)
    {
        int u,v,w;
        cin>>u>>v>>w;
        edge[i] = {u,v,w};
    }
    bellman();
    
    return 0;
}

spfa求最短路

#include <bits/stdc++.h>
using namespace std;

struct node{
    int u,v,w;
}edge[10005];
int n,m,k;
int dist[505];
int dist2[505];
void bellman()
{
    memset(dist,0x3f,sizeof dist);
    dist[1]=0;
    for(int i = 0;i < k;i++)
    {
        memcpy(dist2,dist,sizeof dist);
        for(int j = 1;j <= m;j++)
        {
            int u = edge[j].u;
            int v = edge[j].v;
            int w = edge[j].w;
            dist[v] = min(dist2[u]+w,dist[v]);
            
        }
    }
    
    if(dist[n] >= 0x3f3f3f3f/2) cout<<"impossible"<<"\n";
    else cout<<dist[n]<<"\n";
}

int main()
{
    cin>>n>>m>>k;
    for(int i = 1;i <= m;i++)
    {
        int u,v,w;
        cin>>u>>v>>w;
        edge[i] = {u,v,w};
    }
    bellman();
    
    return 0;
}

spfa判负环

#include <bits/stdc++.h>
using namespace std;
const int N = 2005,M = 1e5+5;
int n,m;
struct node{
    int to,next,w;
}edge[M];
int head[M];
int cnt = 0;
void add(int u,int v,int w)
{
    edge[++cnt] = {v, head[u],w};
    head[u] = cnt;
}
queue<int>q;
bool vis[N];
int dist[N];
int sum[N];
bool spfa()
{

    for(int i = 1;i <= n;i++)
    {
        q.push(i);
        vis[i] = 1;
    }
    
    while(!q.empty())
    {
        int now = q.front();
        q.pop();
        vis[now] = 0;
        for(int i = head[now];i!=-1;i=edge[i].next)
        {
            int to = edge[i].to;
            int w = edge[i].w;
            
            if(dist[to] > dist[now] + w)
            {
                dist[to] = dist[now] + w;
                sum[to] = sum[now] + 1;
                if(sum[to] >= n) return 1;
                if(vis[to] == 0)
                {
                    q.push(to);
                    vis[to] = 1;
                }
            }
        }
        
        
    }
    return 0;
}


int main()
{
    memset(head,-1,sizeof head);
    cin>>n>>m;
    for(int i = 1;i <= m;i++)
    {
        int u,v,w;
        cin>>u>>v>>w;
        add(u,v,w);
    }
    bool f = spfa();
    if(f == 0) cout<<"No"<<"\n";
    else cout<<"Yes"<<"\n";
    return 0;
}

floyd求最短路

#include <bits/stdc++.h>
using namespace std;
int n,m,k;
int d[205][205];

int main()
{
    cin>>n>>m>>k;
    memset(d,0x3f,sizeof d);
    for(int i = 1;i <= n;i++) d[i][i] = 0;
    for(int i = 1;i <= m;i++)
    {
        int u,v,w;
        cin>>u>>v>>w;
        d[u][v] = min(d[u][v] ,w);
    }
    
    for(int l = 1;l <= n;l++)
        for(int i = 1;i <= n;i++)
            for(int j = 1;j <= n;j++)
                d[i][j] = min(d[i][j],d[i][l]+d[l][j]);
    
    for(int i = 1;i <= k;i++)
    {
        int u,v;
        cin>>u>>v;
        if(d[u][v] >= 0x3f3f3f) cout<<"impossible"<<"\n";
        else cout<<d[u][v]<<"\n";
    }
    
    
    return 0;
}

prim求最小生成树

#include <bits/stdc++.h>
using namespace std;

const int N = 505;
int g[N][N], dt[N], st[N];
int n,m;

void prim()
{
	memset(dt, 0x3f, sizeof dt);
	int res = 0;
	dt[1] = 0;
	for(int i = 0; i < n;i++)
	{
		int t = -1;
		for(int j = 1; j <= n;j++)
			if(st[j] == 0 && (t == -1 || dt[j]< dt[t])) t = j;
		if(dt[t] == 0x3f3f3f3f) 
		{
			cout<<"impossible"<<"\n";
			return;	
		}
		st[t] = 1;
		res += dt[t];
		for(int i = 1; i <= n;i++)
			if(dt[i] > g[t][i] && st[i] == 0)	
				dt[i] = g[t][i];
	}
	cout<<res<<"\n";
	
	
}

int main()
{
	memset(g , 0x3f,sizeof g);
	cin>>n>>m;
	for(int i = 1; i <= m;i++)
	{
		int u,v,w;
		cin>>u>>v>>w;
		g[u][v] = g[v][u] = min(g[u][v] , w);
	}
	prim();
	
	return 0;
}

kruskal求最小生成树

#include <bits/stdc++.h>
using namespace std;
const int N = 2e5+5;
int n,m;
struct node{
    int u,v,w;
}e[N];
int f[N];

bool cmp(node a1,node a2)
{
    return a1.w < a2.w;
}

int find(int x)
{
    if(f[x] == x) return x;
    return f[x] = find(f[x]);
}

void kruskal()
{
    int ans = 0,sum = 1;
    for(int i = 1;i <= m;i++)
    {
        int u = e[i].u;
        int v = e[i].v;
        int w = e[i].w;
        
        int uu = find(u);
        int vv = find(v);
        
        if(uu != vv)
        {
            f[uu] = vv;
            ans+=w;
            sum++;
        }
    }
    if(sum < n) 
    {
        cout<<"impossible"<<"\n";
        return;
    }
    cout<<ans<<"\n";
    return;
}

int main()
{
    cin>>n>>m;
    for(int i = 1;i <= n;i++) f[i] = i;
    for(int  i = 1;i <= m;i++)
    {
        int u,v,w;
        cin>>u>>v>>w;
        e[i] = {u,v,w};
    }
    sort(e+1,e+m+1,cmp);
    kruskal();
    
    
    return 0;
}

判定二分图(染色法)

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5+5;
int n,m;

struct node{
    int to,next;
}edge[2*N];
int head[2*N];
int cnt;
int color[N];

void add(int u,int v)
{
    edge[++cnt] = {v,head[u]};
    head[u]=cnt;
}

bool dfs(int u,int col)
{
    color[u] = col;
    
    for(int i = head[u];i;i=edge[i].next)
    {
        int to = edge[i].to;
        if(color[to] == 0)
        {
            if(dfs(to,3 - col) == 0) return 0;
        }
        else
        {
            if(color[to] + col != 3) return 0;
        }
        
    }
    return 1;
    
}

int main()
{
    cin>>n>>m;
    for(int i = 1;i <= m;i++)
    {
        int u,v;
        cin>>u>>v;
        add(u , v);
        add(v, u);
    }
    bool f = 0;
    for(int i = 1;i <= n;i++)
    {
        if(color[i]==0)
        {
            if(dfs(i,1) == 0)
            {
                cout<<"No"<<"\n";
                f = 1;
                break;
            }
        }
    }
    if(f == 0) cout<<"Yes"<<"\n";
    return 0;
}

匈牙利算法/二分图的最大匹配

#include <bits/stdc++.h>
using namespace std;

const int N = 1e5+5;
int n1,n2,m;
struct node{
    int to,next;
}edge[N];
int head[N];
int cnt;
bool vis[505];
int f[505];
void add(int u,int v)
{
    edge[++cnt] = {v , head[u]};
    head[u] = cnt;
}

bool find(int x)
{
    for(int i = head[x];i;i=edge[i].next)
    {
        int to = edge[i].to;
        if(vis[to] == 0)
        {
            vis[to] = 1;
            if(f[to] == 0 || find(f[to]))
            {
                f[to] = x;
                return 1;
            }
            
        }
        
    }
    return 0;
}

int main()
{
    cin>>n1>>n2>>m;
    for(int i = 1;i <= m;i++)
    {
        int u,v;
        cin>>u>>v;
        add(u , v);
    }
    int ans = 0;
    for(int i = 1;i <= n1;i++)
    {
        memset(vis,0,sizeof vis);
        if(find(i) == 1) ans++;
    }
    cout<<ans<<"\n";
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值