杂七杂八的模板

最小表示法(poj1509)

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
#define ll long long
const int maxn=1e5+7;
int T,n;
char s[maxn];

char cc;ll ff;
template<typename T>void read(T& aa) {
	aa=0;ff=1; cc=getchar();
	while(cc!='-'&&(cc<'0'||cc>'9')) cc=getchar();
	if(cc=='-') ff=-1,cc=getchar();
	while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
	aa*=ff;
}

int solve() {
	int i=0,j=1,k=0,t;
	while(i<n&&j<n&&k<n) {
		t=s[(i+k)%n]-s[(j+k)%n];
		if(t==0) k++;
		else {
			if(t>0) i+=k+1;
			else j+=k+1;
			if(i==j) j++;
			k=0;
		}
	}
	return min(i,j);
}

int main() {
	read(T);
	while(T--) {
		scanf("%s",s);
		n=strlen(s);
		printf("%d
",solve()+1);
	}
	return 0;
}

sg函数(hdu1848)

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
#define ll long long
const int maxn=1000+7;
int n[3],f[maxn],sg[maxn],ans;

char cc;ll ff;
template<typename T>void read(T& aa) {
	aa=0;ff=1; cc=getchar();
	while(cc!='-'&&(cc<'0'||cc>'9')) cc=getchar();
	if(cc=='-') ff=-1,cc=getchar();
	while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
	aa*=ff;
}

bool vis[maxn];
int get_sg(int x) {
	memset(vis,0,sizeof(vis));
	for(int i=1;f[i]<=x;++i) vis[sg[x-f[i]]]=1;
	for(int i=0;;++i) if(!vis[i]) return i;
}

int main() {
	f[0]=f[1]=1;
	for(int i=2;i<=1000;++i) {
		f[i]=f[i-1]+f[i-2];
		if(f[i]>1000) break;
	}
	memset(sg,-1,sizeof(sg));sg[0]=0;
	for(int i=1;i<=1000;++i) sg[i]=get_sg(i);
	read(n[0]); read(n[1]); read(n[2]);
	while(n[0]||n[1]||n[2]) {
		ans=sg[n[0]]^sg[n[1]]^sg[n[2]];
		if(ans) printf("Fibo
");
		else printf("Nacci
");
		read(n[0]); read(n[1]); read(n[2]);
	}
	return 0;
}

树hash(bzoj4337)

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
#define ll long long
const int maxn=50+7;
const ll base=1031,bs=1234,bse=5107043,mod=1000000007;
int n,m,fa[maxn],ans;
 
char cc;ll ff;
template<typename T>void read(T& aa) {
    aa=0;ff=1; cc=getchar();
    while(cc!='-'&&(cc<'0'||cc>'9')) cc=getchar();
    if(cc=='-') ff=-1,cc=getchar();
    while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    aa*=ff;
}
 
int fir[maxn],nxt[2*maxn],to[2*maxn],e=0;
void add(int x,int y) {
    to[++e]=y; nxt[e]=fir[x]; fir[x]=e;
    to[++e]=x; nxt[e]=fir[y]; fir[y]=e;
}
 
ll hsh[maxn],now[maxn],zz[maxn],t,fz[maxn],tt;
bool vis[maxn];
void get_hash(int pos) {
    vis[pos]=1;
    for(int y=fir[pos];y;y=nxt[y]) 
        if(!vis[to[y]]) get_hash(to[y]);
    t=0;
    for(int y=fir[pos];y;y=nxt[y]) 
        if(!vis[to[y]]) zz[++t]=now[to[y]];
    vis[pos]=0;
    if(!t) {
        now[pos]=bs;
        return;
    }
    sort(zz+1,zz+t+1);
    for(int i=1;i<=t;++i) {
        now[pos]^=zz[i];
        now[pos]=now[pos]*base%mod;
    }
}
 
int main() {
    read(m);
    for(int i=1;i<=m;++i) {
        read(n);
        memset(fir,0,sizeof(fir)); e=0; tt=0;
        for(int j=1;j<=n;++j) {
            read(fa[j]);
            if(fa[j]) add(fa[j],j);
        }
        for(int j=1;j<=n;++j) {
            memset(now,0,sizeof(now));
            memset(vis,0,sizeof(vis));
            get_hash(j); fz[j]=now[j];
        }
        sort(fz+1,fz+n+1);
        for(int j=1;j<=n;++j) hsh[i]=(hsh[i]^fz[j])*bse%mod;
        for(int j=i;j;--j) if(hsh[j]==hsh[i]) ans=j;
        printf("%d
",ans);
    }
    return 0;
}
/*
4 
4 0 1 1 2 
4 2 0 2 3 
4 0 1 1 1 
4 0 1 2 3 
*/

笛卡尔树(poj1785)

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
#define ll long long
const int maxn=50000+7;
int n,p[maxn],pr[maxn];
char c,s[maxn][117];

char cc;ll ff;
template<typename T>void read(T& aa) {
	aa=0;ff=1; cc=getchar();
	while(cc!='-'&&(cc<'0'||cc>'9')) cc=getchar();
	if(cc=='-') ff=-1,cc=getchar();
	while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
	aa*=ff;
}

int ui;
bool cmp(int x,int y) {
	return strcmp(s[x],s[y])<=0;
}

int son[maxn][2],root;
int zz[maxn],t,last;

void print_ans(int pos) {
	printf("(");
	if(son[pos][0]) print_ans(son[pos][0]);
	printf("%s/%d",s[pos],pr[pos]);
	if(son[pos][1]) print_ans(son[pos][1]);
	printf(")");
}

void solve() {
	t=0;
	memset(son,0,sizeof(son)); root=0;
	for(int i=1;i<=n;++i) {
		last=0;
		while(t&&pr[zz[t]]<pr[p[i]]) {
			last=zz[t];
			t--;
		}
		son[p[i]][0]=last;
		if(!t) root=p[i];
		else son[zz[t]][1]=p[i];
		zz[++t]=p[i];
	}
	print_ans(root);
}

int main() {
	scanf("%d",&n);
	while(n) {
		for(int i=1;i<=n;++i) {
			p[i]=i;
			scanf("%*[ ]%[^/]/%d",s[i],&pr[i]);
		}
		sort(p+1,p+n+1,cmp);
		solve();printf("
");
		scanf("%d",&n);
	} 
	return 0;
}
/*
7 a/7 b/6 c/5 d/4 e/3 f/2 g/1
7 a/1 b/2 c/3 d/4 e/5 f/6 g/7
7 a/3 b/6 c/4 d/7 e/2 f/5 g/1
0
*/

StoerWagner(poj2914)

//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
#define ll long long
#define For(i,a,b) for(int i=(a);i<=(b);++i)
#define Rep(i,a,b) for(int i=(a);i>=(b);--i)
const int maxn=500+7,maxm=maxn*maxn*2;
const ll INF=1e14;
int n,m;

char cc; ll ff;
template<typename T>void read(T& aa) {
	aa=0;cc=getchar();ff=1;
	while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
	if(cc=='-') ff=-1,cc=getchar();
	while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
	aa*=ff;
}

ll v[maxn],wage[maxn],num[maxn][maxn];
bool vis[maxn];
ll StoerWagner() {
	ll rs=INF; int last,now=1;
	For(i,1,n) v[i]=i;
	Rep(nn,n,2) {
		memset(vis,0,sizeof(vis));
		memset(wage,0,sizeof(wage));
		now=1;
		For(i,1,nn-1) {
			vis[now]=1; last=now; now=0;
			For(j,1,nn) if(!vis[j]) {
				wage[j]+=num[v[last]][v[j]];
				if(now==0||wage[j]>wage[now]) now=j;
			}
		}
		rs=min(rs,wage[now]);
		For(i,1,nn) {
			num[v[i]][v[last]]+=num[v[now]][v[i]];
			num[v[last]][v[i]]+=num[v[now]][v[i]];
		}
		v[now]=v[nn];
	}
	return rs;
}

int main() {
	int x,y,z;
	while(scanf("%d%d",&n,&m)==2) {
		memset(num,0,sizeof(num));
		For(i,1,m) {
			read(x); read(y); read(z);
			++x; ++y;
			num[x][y]+=z;
			num[y][x]+=z;
		}
		printf("%lld
",StoerWagner());
	}
	return 0;
}

  

最小割树(bzoj2229)

//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<queue>
using namespace std;
#define ll long long
const int maxn=150+7,maxm=6000+7;
const ll INF=1e14;
int Td,n,m,q,S,T,tot;
ll pp[maxn*maxn],ans[maxn][maxn];

char cc; ll ff;
template<typename T>void read(T& aa) {
	aa=0;cc=getchar();ff=1;
	while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
	if(cc=='-') ff=-1,cc=getchar();
	while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
	aa*=ff;
}

int a[maxn];

struct Node{
	int x,y;ll flow,cap;
	Node(){}
	Node(int x,int y,ll cap):x(x),y(y),cap(cap){flow=0;}
}node[2*maxm];

int cur[maxn],fir[maxn],nxt[2*maxm],e=1;
void add(int x,int y,ll z) {
//	printf("add: %d->%d %lld
",x,y,z);
	node[++e]=Node(x,y,z); nxt[e]=fir[x];fir[x]=e;
	node[++e]=Node(y,x,0); nxt[e]=fir[y];fir[y]=e;
}

int dis[maxn],zz[maxn];
bool bfs() {
	int x,y,z,s=1,t=0;
	memset(dis,-1,sizeof(dis));
	zz[++t]=S; dis[S]=0;
	while(s<=t) {
		x=zz[s++]; if(x==T) return 1;
		for(y=fir[x];y;y=nxt[y]) {
			if(dis[z=node[y].y]!=-1||node[y].flow>=node[y].cap) continue;
			dis[z]=dis[x]+1;
			zz[++t]=z;
		}
	}
	return 0;
}

ll dfs(int pos,ll maxf) {
	if(pos==T||maxf==0) return maxf;
	ll now,rs=0,z;
	for(int &y=cur[pos];y&&maxf;y=nxt[y]) {
		if(dis[z=node[y].y]!=dis[pos]+1||node[y].flow>=node[y].cap) continue;
		now=dfs(z,min(maxf,node[y].cap-node[y].flow));
		node[y].flow+=now;
		node[y^1].flow-=now;
		maxf-=now; rs+=now;
	}
	if(!rs) dis[pos]=-1;
	return rs;
}

ll Dinic() {
	ll rs=0;
	while(bfs()) {
		memcpy(cur,fir,sizeof(fir));
		rs+=dfs(S,INF);
	}
	return rs;
}

bool vis[maxn];
void dfs2(int pos) {
	if(vis[pos]) return;//
	vis[pos]=1; int y,z;
	for(y=fir[pos];y;y=nxt[y]) {
		if(node[y].flow>=node[y].cap) continue;
		z=node[y].y; dfs2(z);
	}
}

void solve(int l,int r) {
	if(l==r) return;
	for(int i=2;i<=e;++i) node[i].flow=0;
	S=a[l]; T=a[r];
	ll x=Dinic();
	memset(vis,0,sizeof(vis));
	dfs2(S);
	for(int i=1;i<=n;++i) if(vis[i]) 
		for(int j=1;j<=n;++j) if(!vis[j]) 
			ans[i][j]=ans[j][i]=min(ans[i][j],x);
	for(int i=l;i<=r;++i) zz[i]=a[i];
	int s=l-1,t=r+1;
	for(int i=l;i<=r;++i) {
		if(vis[zz[i]]) a[++s]=zz[i];
		else a[--t]=zz[i];
	}
	solve(l,s); solve(t,r);
}

void clear() {
	for(int i=1;i<=n;++i) a[i]=i; e=1;
	memset(fir,0,sizeof(fir));
	for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) ans[i][j]=INF;
}

int ef(ll x) {
	int l=0,r=tot+1,mid;
	pp[r]=INF;
	while(l<r-1) {
		mid=(l+r)>>1;
		if(pp[mid]<=x) l=mid;
		else r=mid;
	}
	return l;
}

int main() {
	read(Td); int x,y,z;
	while(Td--) {
		read(n); read(m); 
		clear();
		for(int i=1;i<=m;++i) {
			read(x); read(y); read(z);
			add(x,y,z);
			add(y,x,z);
		}
		solve(1,n); tot=0;
		for(int i=1;i<n;++i) for(int j=i+1;j<=n;++j) pp[++tot]=ans[i][j];
		sort(pp+1,pp+tot+1);
		read(q);
		for(int i=1;i<=q;++i) {
			read(x);
			printf("%d
",ef(x));
		}
		printf("
");
	}
	return 0;
}
/*
2
5 0
1
0
5 0
1
0
*/

  

平面曼哈顿距离最小生成树

对于每个点,以它为中心把平面平均分成八个,每个面里面找一个距离它最近的点连一条边,然后做最小生成树即可。

原因:由最小生成树环切性质,如果形成一个环,最长的那条边是没有用的

如图,在东偏北区域内,|AB|<=|AC|,那么肯定有|AC|>=|BC|

所以AC是不优的。

//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
#define ll long long
#define db double
#define For(i,a,b) for(int i=(a);i<=(b);++i)
#define Rep(i,a,b) for(int i=(a);i>=(b);--i)
const int maxn=1e6+7,maxt=19,W=18;
const db INF=1e9;
int n,m,nowop=0;ll sumtot;
ll px[maxn],py[maxn],p[maxn];

char cc; ll ff;
template<typename T>void read(T& aa) {
	aa=0;cc=getchar();ff=1;
	while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
	if(cc=='-') ff=-1,cc=getchar();
	while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
	aa*=ff;
}

db pf(const db x){return x*x;}
const db eps=1e-12,PI=acos(-1),qr2=sqrt(2);
int dcmp(db x){return fabs(x)<eps? 0:(x>0? 1:-1);}

struct Node{
	int id; db x,y;
}node[maxn];

bool cmp(const Node& a,const Node& b) {
	return dcmp(a.x-b.x)==0? a.y < b.y : a.x < b.x;
}

struct Edge {
	ll x,y,v;
}edge[2*maxn];
int tote;

bool cmp3(const Edge& a,const Edge& b) {
	return a.v<b.v;
}

ll get_len(int x,int y) {
	return abs(px[x]-px[y])+abs(py[x]-py[y]);
}

void insert(int x,int y) {
	if(!x||!y||x==y) return ;
//	printf("insert:%d->%d
",x,y);
	++tote;
	edge[tote].x=x; edge[tote].y=y;
	edge[tote].v=get_len(x,y);
}

int get_max(int x,int y) {
	if((ll)x*y==0) return x+y;
	if(!nowop) {
		if(px[x]+py[x]>px[y]+py[y]) return x;
		else return y;	
	}
	if(nowop==1) {
		if(px[x]-py[x]>px[y]-py[y]) return x;
		else return y;	
	}
	return 0;
}

int ql,qr,qx,maxnum[maxn];
void chge(int pos,int l,int r) {
	maxnum[pos]=get_max(maxnum[pos],qx);
	if(l==r) return;
	int mid=(l+r)>>1;
	if(ql<=mid) chge(pos<<1,l,mid);
	else chge(pos<<1|1,mid+1,r);
}

int q(int pos,int l,int r) {
	if(l>=ql&&r<=qr) return maxnum[pos];
	int mid=(l+r)>>1;
	if(qr<=mid) return q(pos<<1,l,mid);
	if(ql>mid) return q(pos<<1|1,mid+1,r);
	return get_max(q(pos<<1,l,mid),q(pos<<1|1,mid+1,r));
}

void clear(int pos,int l,int r) {
	maxnum[pos]=0;
	if(l==r) return;
	int mid=(l+r)>>1;
	clear(pos<<1,l,mid);
	clear(pos<<1|1,mid+1,r);
}

void doit() {
	For(i,1,n) node[i].id=i,p[i]=node[i].y;
	sort(p+1,p+n+1);
	sort(node+1,node+n+1,cmp);
	For(i,1,n) {
		int pos=lower_bound(p+1,p+n+1,node[i].y)-p;
		ql=1; qr=pos;
		insert(q(1,1,n),node[i].id);
		ql=qr=pos; qx=node[i].id;
		chge(1,1,n);
	}
}

///////////////////////
int fir[maxn],nxt[2*maxn],to[2*maxn],e=0;ll v[2*maxn];
void add(int x,int y,ll z) {
//	printf("add:%d->%d v:%lld
",x,y,z);
	to[++e]=y;nxt[e]=fir[x];fir[x]=e;v[e]=z;
	to[++e]=x;nxt[e]=fir[y];fir[y]=e;v[e]=z;
	sumtot+=z;
}

int pp[maxn];
int find(int x){
	return x==pp[x]? x:pp[x]=find(pp[x]);
}

void Kru() {
	sort(edge+1,edge+tote+1,cmp3);
	For(i,1,n) pp[i]=i;
	int xx,yy,tot=0;
	For(i,1,tote) {
		xx=find(edge[i].x); yy=find(edge[i].y);
		if(xx!=yy) {
			add(edge[i].x,edge[i].y,edge[i].v);
			++tot;
			if(tot==n-1) break;
			pp[xx]=yy;
		}
	}
}

int fa[maxn][maxt],dep[maxn];ll maxlen[maxn][maxt];
void dfs(int pos,int f) {
	fa[pos][0]=f; dep[pos]=dep[f]+1;
	For(i,1,W) {
		fa[pos][i]=fa[fa[pos][i-1]][i-1];
		maxlen[pos][i]=max(maxlen[pos][i-1],maxlen[fa[pos][i-1]][i-1]);
	}
	int y,z;
	for(y=fir[pos];y;y=nxt[y]) {
		if((z=to[y])==f) continue;
		maxlen[z][0]=v[y];
		dfs(z,pos);
	}
}

ll Yth(int x,int y) {
	if(fa[x][0]==y||fa[y][0]==x) return get_len(x,y);
	ll rs=0;
	if(dep[x]!=dep[y]) {
		if(dep[x]<dep[y]) swap(x,y);
		Rep(i,W,0) if(dep[fa[x][i]]>=dep[y]) 
			rs=max(rs,maxlen[x][i]),x=fa[x][i];
	}
	if(x==y) return rs;
	Rep(i,W,0) if(fa[x][i]!=fa[y][i]) {
		rs=max(rs,maxlen[x][i]);
		rs=max(rs,maxlen[y][i]);
		x=fa[x][i]; y=fa[y][i];
	}
	rs=max(rs,maxlen[x][0]);
	rs=max(rs,maxlen[y][0]);
	return rs;
}

int main() {
	read(n);
	For(i,1,n) {read(px[i]); read(py[i]);}
	////////////////////add edge
	//West - South
	For(i,1,n) {
		node[i].x=px[i]-py[i];
		node[i].y=py[i];
	}
	doit();
	//South - West
	clear(1,1,n);
	For(i,1,n) {
		node[i].x=px[i];
		node[i].y=py[i]-px[i];
	}
	doit();
	//West - North
	clear(1,1,n); nowop=1;
	For(i,1,n) {
		node[i].x=px[i]+py[i];
		node[i].y=py[i];
		node[i].y=INF-node[i].y;
	}
	doit();
	//North - West
	clear(1,1,n); nowop=1;
	For(i,1,n) {
		node[i].x=px[i];
		node[i].y=px[i]+py[i];
		node[i].y=INF-node[i].y;
	}
	doit();
	///////////////////
	Kru();
	dfs(1,0);
	read(m); int x,y;
	For(i,1,m) {
		read(x); read(y);
		printf("%lld
",sumtot-Yth(x,y)+get_len(x,y));
	}
	return 0;
}

  

最大权闭合子图(bzoj3996)

//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
#define ll long long
#define db double
#define For(i,a,b) for(int i=(a);i<=(b);++i)
#define Rep(i,a,b) for(int i=(a);i>=(b);--i)
const int maxn=1007*1007,INF=0x3f3f3f3f;
int n,S,T,D[maxn];
bool vis[maxn];

char cc; ll ff;
template<typename T>void read(T& aa) {
	aa=0;cc=getchar();ff=1;
	while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
	if(cc=='-') ff=-1,cc=getchar();
	while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
	aa*=ff;
}

struct Node{
	int x,y,cap,flow;
	Node(){}
	Node(int x,int y,int cap):x(x),y(y),cap(cap){flow=0;}
}node[2*maxn];

int fir[maxn],nxt[2*maxn],e=1;
void add(int x,int y,int z) {
	node[++e]=Node(x,y,z);nxt[e]=fir[x];fir[x]=e;
	node[++e]=Node(y,x,0);nxt[e]=fir[y];fir[y]=e;
}

int dis[maxn],zz[maxn];
bool BFS() {
	memset(dis,-1,sizeof(dis));
	int x,y,z,s=1,t=0;
	zz[++t]=S; dis[S]=0;
	while(s<=t) {
		x=zz[s++]; if(x==T) return 1;
		for(y=fir[x];y;y=nxt[y]) {
			if(dis[z=node[y].y]!=-1||node[y].flow>=node[y].cap) continue;
			dis[z]=dis[x]+1;
			zz[++t]=z;
		}
	}
	return 0;
}

int DFS(int pos,int maxf) {
	if(pos==T||maxf==0) return maxf;
	int rs=0,now,y,z;
	for(y=fir[pos];y&&maxf;y=nxt[y]) {
		if(dis[z=node[y].y]!=dis[pos]+1||node[y].flow>=node[y].cap) continue;
		now=DFS(z,min(maxf,node[y].cap-node[y].flow));
		node[y].flow+=now;
		node[y^1].flow-=now;
		rs+=now; maxf-=now;
	}
	if(!rs) dis[pos]=-1;
	return rs;
}

void Dinic() {
	int rs=0;
	while(BFS()) rs+=DFS(S,INF);
}

void dfs(int pos) {
	if(vis[pos]) return;
	vis[pos]=1;
	for(int y=fir[pos];y;y=nxt[y]) {
		if(node[y].flow>=node[y].cap) continue;
		dfs(node[y].y);
	}
}

int main() {
	read(n); int x,y,z;
	S=n*n+n+1; T=S+1;
	For(i,1,n*n) {
		read(x);
		add(S,i,x);
	}
	For(i,1,n) {
		read(D[i]);
		add(i+n*n,T,D[i]);
	}
	For(i,1,n) For(j,1,n) {
		add((i-1)*n+j,i+n*n,INF);
		if(i!=j) add((i-1)*n+j,j+n*n,INF);
	}
	Dinic();
	dfs(S);
	int ans=0;
	for(y=fir[S];y;y=nxt[y]) {
		if(vis[z=node[y].y]) ans+=node[y].cap; 
	}
	For(i,1,n) if(vis[i+n*n]) ans-=D[i];
	printf("%d",ans);
	return 0;
}

  

朱刘算法

//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
#define ll long long
#define db double
#define For(i,a,b) for(register int i=(a);i<=(b);++i)
#define Rep(i,a,b) for(register int i=(a);i>=(b);--i)
const int maxn=1000+7,maxm=1e6+7;
const ll INF=1e18,inf=1e14;
int n,m;
ll dis[maxn][maxn];

char cc;ll ff;
template<typename T>void read(T& aa) {
	aa=0;ff=1; cc=getchar();
	while(cc!='-'&&(cc<'0'||cc>'9')) cc=getchar();
	if(cc=='-') ff=-1,cc=getchar();
	while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
	aa*=ff;
}

struct Edge{
	int x,y; ll w;
	Edge(){}
	Edge(int x,int y,ll w):x(x),y(y),w(w){}	
}edge[maxm];
int e;

ll d[maxn];
int pr[maxn],id[maxn],vis[maxn];
ll zl(int rt,int n) {
	ll rs=0; int x,y,toth;
	while(1) {
		For(i,1,n) d[i]=INF; d[rt]=0;
		For(i,1,e) {
			x=edge[i].x; y=edge[i].y;
			if(x!=y&&edge[i].w<d[y]) {
				d[y]=edge[i].w;
				pr[y]=x;
			}
		}
		For(i,1,n) if(d[i]==INF) return -1;
		For(i,1,n) vis[i]=id[i]=-1;
		toth=0;
		For(i,1,n) {
			x=i; rs+=d[x];
			while(id[x]==-1&&x!=rt&&vis[x]!=i) {
				vis[x]=i; x=pr[x];
			}
			if(id[x]==-1&&x!=rt) {
				id[x]=++toth;
				for(y=pr[x];y!=x;y=pr[y]) id[y]=toth;
			}
		}
		if(!toth) break;
		For(i,1,n) if(id[i]==-1) id[i]=++toth;
		For(i,1,e) {
			x=edge[i].x; y=edge[i].y;
			if(id[x]!=id[y]) edge[i].w-=d[y];
			edge[i].x=id[x]; edge[i].y=id[y];
		}
		n=toth; rt=id[rt];
	}
	if(rs-inf>=inf) return -1;
	return rs-inf;
}

int main() {
	freopen("a.in","r",stdin);
	freopen("a.out","w",stdout);
	read(n); read(m);
	For(i,1,n+1) For(j,1,n+1) dis[i][j]=INF;
	int x,y; ll w;
	For(i,1,m) {
		read(x); read(y); read(w);
		dis[x][y]=min(dis[x][y],w);
	}
	For(i,1,n) For(j,1,n) if(dis[i][j]!=INF) 
		edge[++e]=Edge(i,j,dis[i][j]);
	For(i,1,n) edge[++e]=Edge(n+1,i,inf);
	printf("%lld
",zl(n+1,n+1));
	return 0;
}

  

原文地址:https://www.cnblogs.com/Serene-shixinyi/p/8321823.html