圖論_模板

1.Prim


void prim()
{
	int i,j,k,min;
	for(i=2;i<=n;i++)
		dis[i]=map[1][i];
	vis[1]=1;
	for(i=2;i<=n;i++)//經過N次遍歷一定能遍歷所有的點 也就是完成了最終目標.
	{
		min=inf;
		for(j=1;j<=n;j++)
		{
			if(vis[j]==0 &&dis[j]<min)
			{
				min=dis[j];
				k=j;
			}
		}
		if(min==inf)
			break;
		vis[k]=1;
		sum+=sqrt(1.0*min);//完成了一次權值加和.
		for(j=2;j<=n;j++)
		{
			if(vis[j]==0 &&dis[j]>map[k][j])
				dis[j]=map[k][j];
		}//更新最優解.
	}
}

2.二分匹配


int  find(int x)  
{  
    for(int i=1;i<=m;i++)  
    {  
        if(vis[i]==0&&map[i][x])  
        {  
            vis[i]=1;  
            if(pri[i]==-1||find(pri[i]))  
            {  
                pri[i]=x;  
                return 1;  
            }  
        }  
    }  
    return 0;  
}  

3.Bellman

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
using namespace std;
int dis[121212];
int u[121212];
int v[121212];
int w[121212];
int main()
{
    int n,m;
    int check;
    while(~scanf("%d%d",&n,&m))
    {
        if(n==0||m==0)break;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%d",&u[i],&v[i],&w[i]);
        }
        for(int i=1;i<=n;i++)
        {
            dis[i]=0x1f1f1f1f;
        }
        dis[1]=0;
        for(int k=1;k<=n-1;k++)//最多遍歷點的次數.
        {
            check=0;
            for(int i=1;i<=m;i++)
            {
                if(dis[v[i]]>dis[u[i]]+w[i])
                {
                    dis[v[i]]=dis[u[i]]+w[i];
                    check=1;
                }
                if(dis[u[i]]>dis[v[i]]+w[i])
                {
                    dis[u[i]]=dis[v[i]]+w[i];
                    check=1;
                }
            }
            if(check==0)break;
        }
        int flag=0;//標記是否有負權迴路...
        for(int i=0;i<=m;i++)
        {
                if(dis[v[i]]>dis[u[i]]+w[i])
                {
                    dis[v[i]]=dis[u[i]]+w[i];
                    flag=1;
                }
                if(dis[u[i]]>dis[v[i]]+w[i])
                {
                    dis[u[i]]=dis[v[i]]+w[i];
                    flag=1;
                }
        }
        if(flag==1){printf("0\n");continue;}
        printf("%d\n",dis[n]);
    }
}

4.Dij


void dijkstra(int s)
{
    d[s]=0;
    for(int k=0;k<n;k++)
    {
        int m=INF;
        for(int i=0;i<n;i++)
        {
            if(!vis[i] && d[i]<=m)
                m=d[s=i];
        }
        vis[s] = 1;
        for(int i=0;i<n;i++)
        {
            d[i]=MIN(d[i],d[s]+w[s][i]);
        }
    }
}


void Dij()
{
	int i,j,k,v,tmp;
	memset(vis,0,sizeof(vis));
	for(i=1;i<=n;i++)//這裏等號很魔怔
	    d[i]=w[1][i];//當然是要起點開始走.
	d[1]=0;
	vis[1]=1;
	for(i=1;i<=n;i++)//爲了連接多少點的控制.//這裏等號一樣魔怔

	{
		tmp=N;
		for(j=1;j<=n;j++)
		{
			if(tmp>d[j]&&!vis[j])
			{
				tmp=d[j];
				v=j;
			}
		}//每次選中的都是距離起點最近的點.v
		vis[v]=1;
		for(k=1;k<=n;k++)
		{
			if(!vis[k])//然後鬆弛.
			d[k]=min(d[k],d[v]+w[v][k]);
		}
	}
}

#include<stdio.h>
#include<string.h>
#include<map>
#include<iostream>
#include<vector>
#include<queue>
const int maxn=30003;
const int INF=0x1f1f1f1f;
int n,m;
using namespace std;
struct Edge
{
    int from,to,dist;
    Edge(int u,int v,int d):from(u),to(v),dist(d) {}
};
string s;
string e;
vector<Edge>edges;//存儲邊的結點信息
vector<int>G[maxn];//鄰接表
bool done[maxn];   //標記是否訪問過
int d[maxn];    //距離數組
map<string,int>cnt;//映射成節點編號
struct heapnode //用於優先隊列自定義
{
    int d,u;
    bool operator <(const heapnode rhs) const
    {
        return d > rhs.d;
    }
    heapnode(int dd,int uu):d(dd),u(uu) {}
};
void init()//初始化必不可少
{
    for(int i=0; i<n; i++)
        G[i].clear();
    edges.clear();
}
void dij( int s)
{
    priority_queue<heapnode>Q;
    for(int i=0; i<=n; i++)//初始化距離數組
        d[i]=INF;
    d[s]=0;
    memset(done ,0,sizeof(done));
    Q.push( heapnode(0,s) );
    while(!Q.empty())
    {
        heapnode x = Q.top();
        Q.pop();
        int u=x.u;
        if(u==cnt[e])
        {
            printf("%d\n",x.d);
            break;
        }
        if(done[u])continue;
        done[u] = true;
        for(int i=0; i<G[u].size(); i++)
        {
            Edge& e=edges[G[u][i]];//取出來一條鄰接邊
            if(d[e.to]>d[u]+e.dist)
            {
                d[e.to] = d[u] + e.dist;
                Q.push((heapnode(d[e.to],e.to)));
            }
        }
    }
}
void addedge(int from,int to,int dist)
{
    edges.push_back(Edge(from,to,dist));
    int m = edges.size();
    G[from].push_back(m-1);
}
int main()
{
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        int t=1;
        int ans=0;
        string str;
        init();
        for(int i=0; i<n; i++)
        {
            cin>>str;
            cnt[str]=t++;
        }
        for(int i=0; i<m; i++)
        {
            string str2;
            int x;
            cin>>str>>str2>>x;
            addedge(cnt[str],cnt[str2],x);
            addedge(cnt[str2],cnt[str],x);
        }
        cin>>s>>e;
        dij(cnt[s]);
        s.clear();
        e.clear();
        cnt.clear();
    }
    return 0;
}

4.Floyd最小環


int ans=0x1f1f1f1f;
for(int i=0; i<n; i++)
{
    for(int j=0; j<i; j++)
    {
        for(int k=j+1; k<i; k++)
        {
            ans=min(ans,map[j][k]+dis[k][i]+dis[i][j]);
        }
    }
    for(int j=0; j<n; j++)
    {
        for(int k=0; k<n; k++)
        {
            map[j][k]=min(map[j][k],map[j][i]+map[i][k]);
        }
    }
}

5.SPFA

int SPFA(int s)
{
    int i;
    bool visit[N] = {false};
    int front = 0, rear = 1;
    memset(queue,0,sizeof(queue));
    for(i=1;i<=n;i++)
    d[i] = MAX;
    queue[front] = s;
    visit[s] = true;
    d[s] = 0;
    while(front<rear)
    {
        int u = queue[front];
        visit[u] = false;
        for(int i=1; i<=n; i++)
        {
            if (d[i]>d[u]+ edges[u][i])
            {
                d[i]= d[u]+edges[u][i];
                if( !visit[i] )
                {
                    visit[i] = true;
                queue[rear++] = i;
                }
            }
        }
        front++;
    }
    return 0;
}

6.最小樹形圖


#define INF 0x7fffffff  
double x[1000];  
double y[1000];  
double w[1000][1000];  
int flag[1000];//判斷是否在有向環裏邊的縮點  
int vis[1000];  
int pre[1000];  
int n,m;  
void init()//不能少了初始化的內容  
{  
    memset(vis, 0, sizeof(vis));  
    memset(flag, 0, sizeof(flag));  
    for(int i=0; i<=n; i++)  
    {  
        w[i][i] = INF;  
        for(int j=i+1; j<=n; j++)  
            w[i][j]=w[j][i]=INF;  
    }  
}  
  
double directed_mst(int u)//u表示根節點  
{  
    double ans=0;  
    memset(vis, 0, sizeof(vis));  
    while(true)  
    {  
        //求最短弧集合E  
        for(int i=1; i<=n; i++)if(i!=u&&!flag[i])  
            {  
                w[i][i]=INF, pre[i] = i;  
                for(int j=1; j<=n; j++)if(!flag[j] && w[j][i]<w[pre[i]][i])  
                {  
                    pre[i] = j;  
                }  
                if(pre[i]==i)return -1;//也可以用dfs預處理判斷凸的連通  
            }  
        //判斷E是否有環  
        int i;  
        for(i=1; i<=n; i++)  
        {  
            if(i!=u&&!flag[i])  
            {  
                int j=i, cnt=0;  
                while(j!=u && pre[j]!=i && cnt<=n) j=pre[j], ++cnt;  
                if(j==u || cnt>n) continue; //最後能找到起點(根)或者是走過的點已經超過了n個,表示沒有有向環  
                break;  
            }  
        }  
        if(i>n)  
        {  
            for(int i=1; i<=n; i++)if(i!=u && !flag[i]) ans+=w[pre[i]][i];  
            return ans;  
        }  
        //有環,進行收縮,把整個環都收縮到一個點i上。  
        int j=i;  
        memset(vis, 0, sizeof(vis));  
        do  
        {  
            ans += w[pre[j]][j], j=pre[j], vis[j]=flag[j]=true;//對環內的點標記,並且直接對環的權值進行加和記錄,在最後找到最小樹形圖之後就不用展開收縮點了  
        }  
        while(j!=i);  
        flag[i] = false; // 環縮成了點i,點i仍然存在  
  
        //收縮點的同時,對邊權值進行改變  
        for(int k=1; k<=n; ++k)if(vis[k])  // 在環中點點  
            {  
                for(int j=1; j<=n; j++)if(!vis[j])   // 不在環中的點  
                    {  
                        if(w[i][j] > w[k][j]) w[i][j] = w[k][j];  
                        if(w[j][k]<INF && w[j][k]-w[pre[k]][k] < w[j][i])  
                            w[j][i] = w[j][k] - w[pre[k]][k];  
                    }  
            }  
    }  
    return ans;  
}  

7.LCA


①離線Tarjan


#include<stdio.h>
#include<string.h>
#include<vector>
using namespace std;
int head[100000];
int f[100000];
int qhead[100000];
int vis[100000];
int dir[100000];
int problem[100000][2];
struct EdgeNode
{
    int from;
    int to;
    int w;
    int lca;
    int next;
}e[100000],q[100000];
int n,m,ask,cont;
int find(int a)
{
    int r=a;
    while(f[r]!=r)
    r=f[r];
    int i=a;
    int j;
    while(i!=r)
    {
        j=f[i];
        f[i]=r;
        i=j;
    }
    return r;
}
void merge(int a,int b)
{
    int A,B;
    A=find(a);
    B=find(b);
    if(A!=B)
    f[B]=A;
}
void add(int from,int to,int w)
{
    e[cont].from=from;
    e[cont].to=to;
    e[cont].w=w;
    e[cont].next=head[from];
    head[from]=cont;
    cont++;
    e[cont].from=to;
    e[cont].to=from;
    e[cont].w=w;
    e[cont].next=head[to];
    head[to]=cont;
    cont++;
}
void addq(int from,int to)
{
    q[cont].from=from;
    q[cont].to=to;
    q[cont].lca=-1;
    q[cont].next=qhead[from];
    qhead[from]=cont;
    cont++;
    q[cont].from=to;
    q[cont].to=from;
    q[cont].lca=-1;
    q[cont].next=qhead[to];
    qhead[to]=cont;
    cont++;
}
void LCA(int u)
{
    f[u]=u;
    vis[u]=1;
    for(int k=head[u];k!=-1;k=e[k].next)
    {
        int to=e[k].to;
        if(vis[to]==0)
        {
            int w=e[k].w;
            dir[to]=dir[u]+w;
            LCA(to);
            merge(u,to);
        }
    }
    for(int k=qhead[u];k!=-1;k=q[k].next)
    {
        int to=q[k].to;
        if(vis[to]==1)
        {
            q[k].lca=find(to);
            q[k^1].lca=q[k].lca;
        }
    }
}

8.Kosaraju

#include<stdio.h>  
#include<string.h>  
using namespace std;  
int head[100000];  
int head2[100000];  
struct EdgeNode  
{  
    int from;  
    int to;  
    int next;  
}e[100000],ee[100000];  
int n,m,cont,cont2,sig;  
int degree[1000000];  
int vis[1000000];  
int num[1000000];  
int color[1000000];  
void add(int from,int to)  
{  
    e[cont].from=from;  
    e[cont].to=to;  
    e[cont].next=head[from];  
    head[from]=cont++;  
}  
void add2(int from,int to)  
{  
    ee[cont2].from=from;  
    ee[cont2].to=to;  
    ee[cont2].next=head2[from];  
    head2[from]=cont2++;  
}  
void Dfs(int u)  
{  
    vis[u]=1;  
    for(int k=head[u];k!=-1;k=e[k].next)  
    {  
        int v=e[k].to;  
        if(vis[v]==0)  
        {  
            Dfs(v);  
        }  
    }  
    num[sig++]=u;  
}  
void Dfs2(int u)  
{  
    vis[u]=1;  
    color[u]=sig;  
    for(int k=head2[u];k!=-1;k=ee[k].next)  
    {  
        int v=ee[k].to;  
        if(vis[v]==0)  
        {  
            Dfs2(v);  
        }  
    }  
}  
void Kosaraju()  
{  
    sig=1;  
    memset(color,0,sizeof(color));  
    memset(vis,0,sizeof(vis));  
    for(int i=1;i<=n;i++)  
    {  
        if(vis[i]==0)  
        {  
            Dfs(i);  
        }  
    }  
    sig=0;  
    memset(vis,0,sizeof(vis));  
    for(int i=n;i>=1;i--)  
    {  
        if(vis[num[i]]==0)  
        {  
            sig++;  
            Dfs2(num[i]);  
        }  
    }  
    for(int i=1;i<=n;i++)  
    {  
        for(int k=head[i];k!=-1;k=e[k].next)  
        {  
            int vv=e[k].to;  
            if(color[vv]!=color[i])  
            {  
                degree[color[i]]++;  
            }  
        }  
    }  
    int tot=0;  
    int tmp=-1;  
    for(int i=1;i<=sig;i++)  
    {  
        if(degree[i]==0)  
        {  
            tot++;  
            tmp=i;  
        }  
    }  
    if(tot==1)  
    {  
        int output=0;  
        for(int i=1;i<=n;i++)  
        {  
            if(color[i]==tmp)output++;  
        }  
        printf("%d\n",output);  
    }  
    else printf("0\n");  
}  
int main()  
{  
    while(~scanf("%d%d",&n,&m))  
    {  
        cont=0;cont2=0;  
        memset(num,0,sizeof(num));  
        memset(degree,0,sizeof(degree));  
        memset(vis,0,sizeof(vis));  
        memset(color,0,sizeof(color));  
        memset(head,-1,sizeof(head));  
        memset(head2,-1,sizeof(head2));  
        for(int i=0;i<m;i++)  
        {  
            int x,y;  
            scanf("%d%d",&x,&y);  
            add(x,y);  
            add2(y,x);  
        }  
        Kosaraju();  
    }  
}  

9.強連通Tarjan


#include<stdio.h>
#include<string.h>
#include<vector>
using namespace std;
vector<int >mp[1000000];
int stack[1000000];
int vis[1000000];
int low[1000000];
int color[1000000];
int dfn[1000000];
int n,m,cnt,sig,tt;
void Tarjan(int u)
{
    vis[u]=1;
    low[u]=dfn[u]=cnt++;
    stack[++tt]=u;
    for(int i=0;i<mp[u].size();i++)
    {
        int v=mp[u][i];
        if(vis[v]==0)
        {
            Tarjan(v);
        }
        if(vis[v]==1)low[u]=min(low[u],low[v]);
    }
    if(dfn[u]==low[u])
    {
        sig++;
        do
        {
            color[stack[tt]]=sig;
            low[stack[tt]]=sig;
            vis[stack[tt]]=2;
        }while(stack[tt--]!=u);
    }
}
void Slove()
{
    cnt=1;
    sig=0;tt=-1;
    memset(vis,0,sizeof(vis));
    for(int i=1;i<=n;i++)
    {
        if(vis[i]==0)
        {
            Tarjan(i);
        }
    }
    if(sig==1)
    {
        printf("Yes\n");
    }
    else printf("No\n");
}
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        if(n==0&&m==0)break;
        for(int i=1;i<=n;i++)mp[i].clear();
        for(int i=0;i<m;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            mp[x].push_back(y);
        }
        Slove();
    }
}

10.Tarjan求割點


#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
int head[100000];
int dfn[100000];
int low[100000];
int ans[100000];
struct EdgeNode
{
    int to;
    int w;
    int next;
}e[100000];
int cont,cnt,root;
void add(int from,int to)
{
    e[cont].to=to;
    e[cont].next=head[from];
    head[from]=cont++;
}
void init()
{
    cont=0;
    cnt=1;
    root=1;
    memset(head,-1,sizeof(head));
    memset(ans,0,sizeof(ans));
    memset(dfn,0,sizeof(dfn));
    memset(low,0,sizeof(low));
}
// 樹邊 low[u]=min(low[u],low[v]);
// 回邊 low[u]=min(low[u],dfn[v]);
void Tarjan(int u,int from)
{
    int son=0;
    dfn[u]=low[u]=cnt;
    cnt++;
    for(int i=head[u];i!=-1;i=e[i].next)
    {
        int v=e[i].to;
        if(dfn[v]==0)
        {
            Tarjan(v,u);
            low[u]=min(low[u],low[v]);
            if(u==root)
            {
                son++;
                if(son>1)ans[u]=1;
            }
            if(low[v]>=dfn[u]&&u!=root)
            {
                ans[u]=1;
            }
        }
        else if(from!=v)low[u]=min(low[u],dfn[v]);
    }
}

11.FF最大流


#include<stdio.h>
#include<queue>
#include<string.h>
using namespace std;
int map[350][350];
int pre[350];
int vis[350];
int m,n,maxflow;
int s,t;
int Bfs(int ss,int tt)
{
    memset(vis,0,sizeof(vis));
    memset(pre,0,sizeof(pre));
    queue<int >s;
    s.push(ss);
    vis[ss]=1;
    while(!s.empty())
    {
        int u=s.front();
        if(u==tt)return 1;
        s.pop();
        for(int v=1;v<=n;v++)
        {
            if(vis[v]==0&&map[u][v]!=0)
            {
                vis[v]=1;
                pre[v]=u;
                s.push(v);
            }
        }
    }
    return 0;
}
void Ford_Fulkerson()
{
    maxflow=0;
    while(1)
    {
        if(Bfs(s,t)==1)
        {
            int Min=0x3f3f3f3f;
            for(int i=t;i!=s;i=pre[i])
            {
                Min=min(Min,map[pre[i]][i]);
            }
            for(int i=t;i!=s;i=pre[i])
            {
                map[pre[i]][i]-=Min;
                map[i][pre[i]]+=Min;
            }
            maxflow+=Min;
        }
        else break;
    }
    printf("%d\n",maxflow);
}
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        s=1;t=n;
        memset(map,0,sizeof(map));
        for(int i=1;i<=m;i++)
        {
            int x,y,w;
            scanf("%d%d%d",&x,&y,&w);
            map[x][y]+=w;
        }
        Ford_Fulkerson();
    }
}

12.EK最大流


#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<queue>
#include<string.h>
using namespace std;
int head[2550];
struct node
{
    int from,to,w,next;
}e[2550*2550];
int vis[2550];
int pre[255000];
int n,m,s,t,sum,cont;
void add(int from,int to,int w)
{
    e[cont].from=from;
    e[cont].to=to;
    e[cont].w=w;
    e[cont].next=head[from];
    head[from]=cont++;
    e[cont].from=to;
    e[cont].to=from;
    e[cont].w=0;
    e[cont].next=head[to];
    head[to]=cont++;
}
int Ek_Bfs(int start,int end)
{
    memset(vis,0,sizeof(vis));
    memset(pre,-1,sizeof(pre));
    vis[start]=1;
    queue<int >s;
    s.push(start);
    while(!s.empty())
    {
        int u=s.front();
        if(u==end)return 1;
        s.pop();
        for(int i=head[u];i!=-1;i=e[i].next)
        {
            int v=e[i].to;
            if(vis[v]==0&&e[i].w>0)
            {
                vis[v]=1;
                pre[v]=i;
                s.push(v);
            }
        }
    }
    return 0;
}
void Edmond_Karp()
{
    int maxflow=0;
    int minn;
    while(Ek_Bfs(s,t))
    {
        minn=0x3f3f3f3f;
        int u=t;
        while(u!=s)
        {
            minn=min(e[pre[u]].w,minn);
            u=e[pre[u]].from;
        }
        u=t;
        while(pre[u]!=-1)
        {
            e[pre[u]].w-=minn;
            e[pre[u]^1].w+=minn;
            u=e[pre[u]].from;
        }
        maxflow+=minn;
    }
}

13.Dinic

int makedivv()
{
    memset(divv,0,sizeof(divv));
    divv[ss]=1;
    queue<int >s;
    s.push(ss);
    while(!s.empty())
    {
        int u=s.front();
        if(u==tt)return 1;
        s.pop();
        for(int i=head[u];i!=-1;i=e[i].next)
        {
            int v=e[i].to;
            int w=e[i].w;
            if(w&&divv[v]==0)
            {
                divv[v]=divv[u]+1;
                s.push(v);
            }
        }
    }
    return 0;
}
int Dfs(int u,int maxflow,int tt)
{
    if(tt==u)return maxflow;
    int ret=0;
    for(int &i=cur[u];i!=-1;i=e[i].next)
    {
        int v=e[i].to;
        int w=e[i].w;
        if(w&&divv[v]==divv[u]+1)
        {
            int f=Dfs(v,min(maxflow-ret,w),tt);
            e[i].w-=f;
            e[i^1].w+=f;
            ret+=f;
            if(ret==maxflow)return ret;
        }
    }
    return ret;
}
int Dinic()
{
    int ans=0;
    while(makedivv()==1)
    {
        memcpy(cur,head,sizeof(head));
        ans+=Dfs(ss,INF,tt);
    }
    return ans;
}

14.費用流


#include<stdio.h>  
#include<string.h>  
#include<queue>  
using namespace std;  
struct node  
{  
    int from;  
    int to;  
    int w;  
    int f;  
    int next;  
    int num;  
}e[15151515];  
int n,m,ss,tt,cont;  
int path[151515];  
int pre[151515];  
int head[151515];  
int dis[151515];  
int vis[151515];  
void add(int from,int to,int w,int f)  
{  
    e[cont].from=from;  
    e[cont].to=to;  
    e[cont].f=f;  
    e[cont].w=w;  
    e[cont].num=cont;  
    e[cont].next=head[from];  
    head[from]=cont++;  
}  
int SPFA()  
{  
    queue<int >s;  
    s.push(ss);  
    memset(pre,-1,sizeof(pre));  
    memset(path,-1,sizeof(path));  
    for(int i=1;i<=tt;i++)dis[i]=0x3f3f3f3f;  
    dis[ss]=0;  
    memset(vis,0,sizeof(vis));  
    vis[ss]=1;  
    while(!s.empty())  
    {  
        int u=s.front();  
        s.pop();  
        vis[u]=0;  
        for(int i=head[u];i!=-1;i=e[i].next)  
        {  
            int v=e[i].to;  
            int w=e[i].w;  
            int f=e[i].f;  
            if(f&&dis[v]>dis[u]+w)  
            {  
                dis[v]=dis[u]+w;  
                pre[v]=u;  
                path[v]=e[i].num;  
                if(vis[v]==0)  
                {  
                    s.push(v);  
                    vis[v]=1;  
                }  
            }  
        }  
    }  
    if(dis[tt]!=0x3f3f3f3f)return 1;  
    else return 0;  
}  
void Min_costflow()  
{  
    int ans=0;  
    int maxflow=0;  
    while(SPFA()==1)  
    {  
        int minn=0x3f3f3f3f;  
        for(int i=tt;i!=ss;i=pre[i])  
        {  
            minn=min(minn,e[path[i]].f);  
        }  
        maxflow+=minn;  
        ans+=dis[tt]*minn;  
        for(int i=tt;i!=ss;i=pre[i])  
        {  
            e[path[i]].f-=minn;  
            e[path[i]^1].f+=minn;  
        }  
    }  
    printf("%d\n",ans);  
}  
int main()  
{  
    while(~scanf("%d%d",&n,&m))  
    {  
        ss=n+1;  
        tt=ss+1;  
        cont=0;  
        memset(head,-1,sizeof(head));  
        for(int i=0;i<m;i++)  
        {  
            int x,y,w;  
            scanf("%d%d%d",&x,&y,&w);  
            add(x,y,w,1);  
            add(y,x,-w,0);  
            add(y,x,w,1);  
            add(x,y,-w,0);  
        }  
        add(ss,1,0,2);  
        add(1,ss,0,0);  
        add(n,tt,0,2);  
        add(tt,n,0,0);  
        Min_costflow();  
    }  
}  

15.Km最優二分匹配


#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
#define INF 0x3f3f3f3f
int a[500][500];
int visx[500];
int visy[500];
int lx[500];
int ly[500];
int match[500];
int n;
int low;
int find(int u)
{
    visx[u]=1;
    for(int i=1;i<=n;i++)
    {
        if(visy[i]==1)continue;
        int tmp=lx[u]+ly[i]-a[u][i];
        if(tmp==0)
        {
            visy[i]=1;
            if(match[i]==-1||find(match[i]))
            {
                match[i]=u;
                return 1;
            }
        }
        else if(low>tmp)low=tmp;
    }
    return 0;
}
void KM()
{
    memset(match,-1,sizeof(match));
    memset(lx,0,sizeof(lx));
    memset(ly,0,sizeof(ly));
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            lx[i]=max(lx[i],a[i][j]);
        }
    }
    for(int i=1;i<=n;i++)
    {
        while(1)
        {
            memset(visx,0,sizeof(visx));
            memset(visy,0,sizeof(visy));
            low=INF;
            if(find(i))break;
            for(int i=1;i<=n;i++)
            {
                if(visx[i])lx[i]-=low;
                if(visy[i])ly[i]+=low;
            }
        }
    }
    int sum=0;
    for(int i=1;i<=n;i++)
    {
        sum+=a[match[i]][i];
    }
    printf("%d\n",sum);
}
int main()
{
    while(~scanf("%d",&n))
    {
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                scanf("%d",&a[i][j]);
            }
        }
        KM();
    }
}

16.點雙聯通


void Tarjan(int u,int from)  
{  
    vis[u]=1;  
    dfn[u]=low[u]=cnt++;  
    stack[++tot]=u;  
    for(int i=0;i<mp[u].size();i++)  
    {  
        int v=mp[u][i];  
        if(v==from)continue;  
        if(vis[v]==0)  
        {  
            Tarjan(v,u);  
            low[u]=min(low[u],low[v]);  
        }  
        else low[u]=min(low[u],low[v]);  
    }  
    if(low[u]==dfn[u])  
    {  
        sig++;  
        do  
        {  
            color[stack[tot]]=sig;  
            vis[stack[tot]]=-1;  
        }  
        while(stack[tot--]!=u);  
    }  
}  

17.邊雙連通


void Tarjan(int u,int from)
{
    vis[u]=1;
    dfn[u]=low[u]=cnt++;
    stack[++tt]=u;
    int flag=0;
    for(int i=0;i<mp[u].size();i++)
    {
        int v=mp[u][i];
        if(vis[v]==0)
        {
            Tarjan(v,u);
            low[u]=min(low[u],low[v]);
        }
        else if(v==from)
        {
            if(flag)low[u]=min(low[u],dfn[v]);
            flag++;
        }
        else low[u]=min(low[u],low[v]);
    }
    if(low[u]==dfn[u])
    {
        sig++;
        do
        {
            color[stack[tt]]=sig;
            vis[stack[tt]]=-1;
        }
        while(stack[tt--]!=u);
    }
}

18.Floyd最小環+輸出路徑


#include<stdio.h>  
#include<string.h>  
using namespace std;  
int map[105][105];  
int dis[105][105];  
int main()  
{  
    int t;  
    scanf("%d",&t);  
    while(t--)  
    {  
        int n,m;  
        scanf("%d%d",&n,&m);  
        for(int i=1;i<=n;i++)  
        {  
            for(int j=1;j<=n;j++)  
            {  
                dis[i][j]=map[i][j]=99999999;  
            }  
        }  
        for(int i=0;i<m;i++)  
        {  
            int x,y,w;  
            scanf("%d%d%d",&x,&y,&w);  
            if(map[x][y]>w)  
            {  
                map[x][y]=map[y][x]=w;  
                dis[x][y]=dis[y][x]=w;  
            }  
        }  
        int ans=0;  
        int output=99999999;  
        for(int i=1;i<=n;i++)  
        {  
            for(int j=1;j<i;j++)//  
            {  
                for(int k=j+1;k<i;k++)  
                {  
                    if(dis[j][k]+map[k][i]+map[i][j]<output)  
                    {  
                        output=dis[j][k]+map[k][i]+map[i][j];  
                        ans=1;  
                    }  
                    else if(dis[j][k]+map[k][i]+map[i][j]==output)  
                    {  
                        ans++;  
                    }  
                }  
            }  
            for(int j=1;j<=n;j++)  
            {  
                for(int k=1;k<=n;k++)  
                {  
                    if(dis[j][k]>dis[j][i]+dis[i][k])  
                    {  
                        dis[j][k]=dis[j][i]+dis[i][k];  
                    }  
                }  
            }  
        }  
        printf("%d %d\n",output,ans);  
    }  
}


#include<stdio.h>
#include<string.h>
#include<iostream>
#include<map>
#include<stack>
using namespace std;
map<string,int >s;
map<int,string>re;
int n;
int path[605][605];
int mp[605][605];
int dist[605][605];
void add(int u,int v)
{
    mp[u][v]=dist[u][v]=1;
}
void init()
{
    memset(path,0,sizeof(path));
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            mp[i][j]=dist[i][j]=0x3f3f3f3f;
        }
    }
}
void getPath(int i ,int j){
    if(i==j) return;
    if(path[i][j]==0) cout<<re[j]<<" ";
    else{
        getPath(i,path[i][j]);
        getPath(path[i][j],j);
    }

}
void Slove()
{

    int x,y,z;
    int minn=0x3f3f3f3f;
    for(int k=1;k<=n;k++)
    {
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                if(dist[i][j]!=0x3f3f3f3f&&mp[j][k]!=0x3f3f3f3f&&mp[k][i]!=0x3f3f3f3f)
                {
                    if(dist[i][j]+mp[j][k]+mp[k][i]<minn)
                    {
                        x=i,y=j,z=k;
                        minn=dist[i][j]+mp[j][k]+mp[k][i];
                    }
                }
            }
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                if(dist[i][k]!=0x3f3f3f3f&&dist[k][j]!=0x3f3f3f3f)
                {
                    if(dist[i][k]+dist[k][j]<dist[i][j])
                    {
                        dist[i][j]=dist[i][k]+dist[k][j];
                        path[i][j]=k;
                    }
                }
            }
        }
    }
    for(int i=1;i<=n;i++)
    {
        if(mp[i][i]==1)
        {
            cout<<re[i]<<endl;
            return ;
        }
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            if(mp[i][j]==1&&mp[j][i]==1)
            {
                cout<<re[i]<<" "<<re[j]<<" "<<endl;
                return ;
            }
        }
    }
    if(minn==0x3f3f3f3f)printf("SHIP IT\n");
    else
    {
        cout<<re[x]<<" ";
        getPath(x,y);
        cout<<re[z]<<endl;
    }
}
int main()
{
    while(~scanf("%d",&n))
    {
        init();
        int cnt=0;
        for(int i=1;i<=n;i++)
        {
            char temp[100000];scanf("%s",temp);
            s[temp]=++cnt;
            re[cnt]=temp;
        }
        for(int i=1;i<=n;i++)
        {
            char temp[100000];scanf("%s",temp);
            char sss[100000];
            int u=s[temp];
            int d;scanf("%d",&d);
            getchar();
            for(int j=0;j<d;j++)
            {
                int l=0;
                int flag=0;
                gets(temp);
                int len=strlen(temp);
                for(int j=0;j<len;j++)
                {
                    if(temp[j]==' ')
                    {
                        flag=1;
                        continue;
                    }
                    if(temp[j]==','||j==len-1)
                    {
                        if(j==len-1)sss[l++]=temp[j];
                        flag=0;
                        sss[l]='\0';
                        int v=s[sss];
                        l=0;
                        add(u,v);
                        continue;
                    }
                    if(flag==1)
                    {
                        sss[l++]=temp[j];
                    }
                }
            }
        }
        Slove();
    }
}

19.2-sat輸出可行解


//LightOJ 1251
#include<stdio.h>
#include<string.h>
#include<vector>
#include<queue>
using namespace std;
int output[40005];
int vis[70005];
int low[70005];
int dfn[70005];
int print[70005];
int stack[70005];
int color[70005];
int pos[70005];
int degree[70005];
vector<int >mp[70005];
vector<int >mp2[70005];
int n,m,sig,cnt,tot,cont;
void add(int x,int y)
{
    mp[x].push_back(y);
}
void top()
{
    memset(print,0,sizeof(print));
    queue<int >s;
    for(int i=1;i<=sig;i++)
    {
        if(degree[i]==0)
        {
            s.push(i);
        }
    }
    while(!s.empty())
    {
        int u=s.front();
        if(print[u]==0)
        {
            print[u]=1;print[pos[u]]=2;
        }
        s.pop();
        for(int i=0;i<mp2[u].size();i++)
        {
            int v=mp2[u][i];
            degree[v]--;
            if(degree[v]==0)s.push(v);
        }
    }
    cont=0;
    for(int i=1;i<=n;i++)if(print[color[i]]==1)output[cont++]=i;
}
void Tarjan(int u)
{
    vis[u]=1;
    dfn[u]=low[u]=cnt++;
    stack[++tot]=u;
    for(int i=0;i<mp[u].size();i++)
    {
        int v=mp[u][i];
        if(vis[v]==0)Tarjan(v);
        if(vis[v]==1)low[u]=min(low[u],low[v]);
    }
    if(low[u]==dfn[u])
    {
        sig++;
        do
        {
            vis[stack[tot]]=-1;
            color[stack[tot]]=sig;
        }
        while(stack[tot--]!=u);
    }
}
int Slove()
{
    sig=0;
    cnt=1;
    tot=-1;
    memset(degree,0,sizeof(degree));
    memset(stack,0,sizeof(stack));
    memset(dfn,0,sizeof(dfn));
    memset(low,0,sizeof(low));
    memset(vis,0,sizeof(vis));
    memset(color,0,sizeof(color));
    for(int i=1;i<=n*2;i++)
    {
        if(vis[i]==0)
        {
            Tarjan(i);
        }
    }
    for(int i=1;i<=n;i++)
    {
        if(color[i]==color[i+n])return 0;
        pos[color[i]]=color[i+n];
        pos[color[i+n]]=color[i];
    }
    for(int i=1;i<=n*2;i++)
    {
        for(int j=0;j<mp[i].size();j++)
        {
            int v=mp[i][j];
            if(color[i]!=color[v])
            {
                degree[color[i]]++;
                mp2[color[v]].push_back(color[i]);
            }
        }
    }
    top();
    return 1;
}
int main()
{
    int t;
    int kase=0;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&m,&n);
        for(int i=1;i<=60000;i++)mp[i].clear(),mp2[i].clear();
        for(int i=0;i<m;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            int xx=x;int yy=y;
            if(x<0)x=-x;
            if(y<0)y=-y;
            if(xx>0&&yy>0)add(x+n,y),add(y+n,x);
            if(xx>0&&yy<0)add(x+n,y+n),add(y,x);
            if(xx<0&&yy>0)add(x,y),add(y+n,x+n);
            if(xx<0&&yy<0)add(x,y+n),add(y,x+n);
        }
        int ans=Slove();
        printf("Case %d: ",++kase);
        if(ans==1)
        {
            printf("Yes\n");
            printf("%d",cont);
            for(int i=0;i<cont;i++)
            {
                printf(" %d",output[i]);
            }
            printf("\n");
        }
        else printf("No\n");
    }
}






發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章