蒟蒻求助费用流板子
  • 板块UVA1411 Ants
  • 楼主__zzy__
  • 当前回复0
  • 已保存回复0
  • 发布时间2022/3/17 22:10
  • 上次更新2023/10/28 06:21:24
查看原帖
蒟蒻求助费用流板子
478552
__zzy__楼主2022/3/17 22:10
#include <bits/stdc++.h>
using namespace std;
#define gc getchar
#define pc(x) putchar(x)
#define ll long long
int a[201],b[201],n,head[202],ecnt=1,match[101],pre[202],to[20402],ne[20402],cap[20402];
ll dis[2002],c[20402];
bool vis[202];
deque<int> q;
/*const int LEN=1<<21,inf=2147483647;
char BUF[LEN],*Pin,*Pin_last,PUF[LEN],*Pout=PUF,*Pout_last=PUF+LEN-1;
inline char gc(){
	return Pin==Pin_last&&(Pin_last=(Pin=BUF)+fread(BUF,1,LEN,stdin),Pin==Pin_last)?EOF:*Pin++;
}
inline void pc(char x){
	if(Pout==Pout_last) fwrite(PUF,1,Pout-PUF,stdout),Pout=PUF;
	*Pout++=x;
}*/
int read(){
	int x=0,y=1;
	char ch=gc();
	while(ch<48||ch>57){
	    if(ch=='-') y=-1;
	 	ch=gc();
	}while(ch>47&&ch<58) x=x*10+ch-48,ch=gc();
	return x*y;
}
void write(int x){
    if(x>9) write(x/10);
    pc(x%10+48);
}
bool spfa(int t){//spfa找从源点0到汇点t的最短路
	memset(dis,0x3f,sizeof(dis)),memset(vis,0,sizeof(vis)),q.push_front(0),dis[0]=0,vis[0]=1,pre[t]=-1;
	while(!q.empty()){
		int x=q.front();
		q.pop_front(),vis[x]=0;
		for(int i=head[x];i;i=ne[i]){
			int y=to[i];
			if(cap[i]&&dis[y]>dis[x]+c[i]){
				dis[y]=dis[x]+c[i],pre[y]=i^1;
				if(!vis[y]) vis[y]=1,!q.empty()&&dis[y]<=dis[q.front()]?q.push_front(y):q.push_back(y);
			}
		}
	}return ~pre[t];
}
void ae(int x,int y,ll cost){
	to[++ecnt]=y,ne[ecnt]=head[x],head[x]=ecnt,c[ecnt]=cost,cap[ecnt]=1,to[++ecnt]=x,ne[ecnt]=head[y],head[y]=ecnt,c[ecnt]=-cost,cap[ecnt]=0;
}
signed main(){
	//freopen("data.in","r",stdin);
	//freopen("data.out","w",stdout);
	while(cin>>n){
		int n=read(),m=n+n,t=m+1,ans=0;
		memset(head,0,sizeof(head)),ecnt=1;//初始化
		for(int i=1;i<=n;i++) a[i]=read(),b[i]=read(),ae(0,i,0);//源点到每个白点连一条费用为0,流量为1的边
		for(int i=n+1;i<=m;i++) a[i]=read(),b[i]=read(),ae(i,t,0);//每个黑点到汇点连一条费用为0,流量为1的边
		for(int i=1;i<=n;i++){
			int x=a[i],y=b[i];//每个白点到每个黑点连一条费用为其距离的平方,流量为1的边
			for(int j=1+n;j<=m;j++) ae(i,j,(ll)(a[j]-x)*(a[j]-x)+(b[j]-y)*(b[j]-y));
		}while(spfa(t)){
			int u=t,p;
			while(u){//找到一条可行的增广路就回溯
				p=pre[u];
				if(u!=t&&u>n) match[to[p]]=u-n;//如果该点为黑点,那么就把这条增广路上它的前向边的白点和该点匹配
				cap[p]++,cap[p^1]--,u=to[p];
			} 
		}for(int i=1;i<=n;i++) write(match[i]),pc('\n');
	}return 0;
}

udebug上的数据太大了,自己本地随机数据的话很容易有三点共线的情况,求各位大佬看看蒟蒻是不是犯了什么zz错误

2022/3/17 22:10
加载中...