常用图论算法

最小费用最大流模板:

#include<cstdio> 
#include<iostream> 
#include<cstdlib> 
#include<cmath> 
#include<cstring> 
#include<queue> 
#include<vector> 
#include<algorithm> 
#define LL long long 
#define CLEAR(xxx) memset(xxx,0,sizeof(xxx))    
using namespace std;      
      
const int inf=1e9;       
const int maxn=1000+5;       

int N,n,m,maxflow,mincost,last[maxn];   

inline void _read(int &x){       
    char ch=getchar(); bool mark=false;       
    for(;!isdigit(ch);ch=getchar())if(ch=='-')mark=true;       
    for(x=0;isdigit(ch);ch=getchar())x=x*10+ch-'0';       
    if(mark)x=-x;       
}       

struct Edge{ 
    int from,to,res,w,Next; 
    Edge(int from,int to,int w,int res,int Next):from(from),to(to),w(w),res(res),Next(Next){} 
}; 
vector<Edge> edge; 

void Addedge(int from,int to,int w,int res){ 
    edge.push_back(Edge(from,to,w,res,last[from])); 
    last[from]=edge.size()-1; 
    edge.push_back(Edge(to,from,-w,0,last[to])); 
    last[to]=edge.size()-1; 
} 
   
int path[maxn], dist[maxn];            
bool vis[maxn];  
      
struct SPFA{       
    int  n;            
    void init(int n){ 
        this->n =n; 
        memset(last,-1,sizeof(last)); 
    }                          
    bool find(int s,int t){       
        int i;       
        CLEAR(vis);        
        for(i=1;i<=n;i++) dist[i]=inf; 
        memset(path,-1,sizeof(path)) ;      
        dist[s]=0;  path[s]=0 ;vis[s]=true;   
        queue <int> q;  q.push(s);       
        while(!q.empty()){       
            int x=q.front();       
            q.pop();vis[x]=false;  
             for(i=last[x];i!=-1;i=edge[i].Next){   
                 Edge& e=edge[i];         
                if(e.res>0&&dist[x]+e.w<dist[e.to]){       
                    dist[e.to]=dist[x]+e.w; 
                    path[e.to]=i;       
                    if(!vis[e.to]){       
                        q.push(e.to) ;       
                        vis[e.to]=true;       
                    }       
                }        
            }       
        }   
        return dist[t]<inf;         
    }       
}spfa;   

void Addflow(int s,int t){ 
    int flow=inf,i; 
    for(i=t; i!=s&&edge[path[i]].from!=0;i=edge[path[i]].from) 
        flow=min(flow,edge[path[i]].res); 
    maxflow+=flow; 
    mincost+=dist[t]; 
    for(i=t;i!=s;i=edge[path[i]].from){ 
        int x=path[i]; 
        edge[x].res-=flow; 
        edge[x^1].res+=flow; 
    } 
}   

int main(){ 
    int i,j,k,x,y,z,cnt=0; 
    N=maxflow=mincost=0; 
    _read(n); _read(m); 
    spfa.init(N=n+2);
    for(i=1;i<=m;i++){ 
        _read(x); _read(y); _read(z); 
        Addedge(x,y,z,1);  
        Addedge(y,x,z,1);
    } 
    Addedge(N-1,1,0,2); 
    Addedge(n,N,0,2); 
    while(spfa.find(N-1,N))Addflow(N-1,N); 
    cout<<mincost<<endl; 
    return 0;
}   

最大流:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#define clear(xxx) memset(xxx,0,sizeof(xxx))
using namespace std;
const int inf=1e9;
int dis[4005],cnt[4005],n,x,y,z,m;
int N;
int tot_edge=0;
struct line{
	int from,to,remain,acc;
	int fan;
};
line edge[2000005];
int last[2005],_next[1000005];
void add_edge(int x,int y,int c,int accom){
	tot_edge++;
	edge[tot_edge].from=x;
	edge[tot_edge].to=y;
	edge[tot_edge].acc=accom;
	edge[tot_edge].remain=c;
	_next[tot_edge]=last[x];
	last[x]=tot_edge;
	tot_edge++;
	edge[tot_edge].from=y;
	edge[tot_edge].to=x;
	edge[tot_edge].acc=0;
	edge[tot_edge].remain=0;
	_next[tot_edge]=last[y];
	last[y]=tot_edge;
	edge[tot_edge].fan=tot_edge-1;
	edge[tot_edge-1].fan=tot_edge;
}
int sap(int u,int flow){
	int v,temp,delta=0;
	if(u==N+2)return flow;
	for(int h=last[u];h;h=_next[h]){
		v=edge[h].to;
		if(edge[h].remain&&dis[u]==dis[v]+1){
			temp=sap(v,min(flow-delta,edge[h].remain));
			edge[h].remain-=temp;
			edge[edge[h].fan].remain+=temp;
			delta+=temp;
			if(delta==flow||dis[N+1]>=N+2)return delta;
		}
	}
	if(dis[N+1]>N+2)return delta;
	cnt[dis[u]]--;
	if(cnt[dis[u]]==0)dis[N+1]=N+2;
	dis[u]++;
	cnt[dis[u]]++;
	return delta;
}
int main(){
	int tot=0,i,j,k,t=0,t3,t4;
	cin>>n>>m;
	N=n+m;
	for(i=1;i<=n;i++){
		add_edge(i+m,N+2,1,1);
		int x;
		while(scanf("%d",&x)!=EOF&&x!=0){
			add_edge(x,m+i,1,1);
		}
	}
	for(i=1;i<=m;i++)add_edge(N+1,i,1,1);
	while(dis[N+1]<N+2){
		t+=sap(N+1,inf);
	}
	cout<<t;
}

dijkstra+heap:

#include<cstdio>  
#include<iostream>
#include<cstring>  
#include<queue>  
#include<vector>   
 
#define CLEAR(XXX) memset((XXX),0,sizeof(XXX))
using namespace std; 
 
const int inf=1e9;  
const int maxn=1005,maxm=1005;  
 
int n,m;
  
inline void _read(int &x){  
    char ch=getchar(); bool mark=false;  
    for(;!isdigit(ch);ch=getchar())if(ch=='-')mark=true;  
    for(x=0;isdigit(ch);ch=getchar())x=x*10+ch-'0';  
    if(mark)x=-x;  
}  
struct Edge{  
    int from,to,w;  
    Edge(int from,int to,int w):from(from),to(to),w(w){}
};
struct node{   //建小根堆用 
	int d,u;
	node (int d,int u):d(d),u(u){}
	bool operator < (const node& a)const {
		return d>a.d;	
	}
};    
struct Dijstra{  
    int  n,m;  
    vector<Edge> edge;  
    int last[maxm],Next[maxm],dist[maxn];   
    bool vis[maxn];  
    
    void init(int n){  
        this->n = n;  
        m=0;  
        CLEAR(last);  CLEAR(Next);  
        edge.clear();  
        edge.push_back(Edge(0,0,0));  
    }  
    void add_edge(int from,int to,int dist){  
        edge.push_back(Edge(from,to,dist));  
        m=edge.size()-1;  
        Next[m]=last[from];  
        last[from]=m;  
    }  
    void solve(int s){     
        int i;     
        priority_queue <node> q;    
        CLEAR(vis);       
        for(i=1;i<=n;i++) dist[i]=inf;     
        dist[s]=0;   
        q.push(node(0,s));        
        while(!q.empty()){    
            int x=q.top().u;    
            q.pop();     
            for(i=last[x];i;i=Next[i]){    
                Edge& e=edge[i];      
                if(dist[e.from]+e.w<dist[e.to]){     
                    dist[e.to]=dist[e.from]+e.w;          
                    q.push(node(dist[e.to],e.to)) ;          
                    }     
                }           
        }     
    } 
int main(){  
    Dijstra solver;
	int  i,j,x,y,w;
	_read(n);_read(m);
	solver.init(n);
	for(i=1;i<=m;i++){
		_read(x);_read(y);_read(w);
		solver.add_edge(x,y,w);
	}
	_read(x);_read(y);
	solver.solve(x);
	printf("%d",solver.dist[y]);
	return 0;
}  


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值