其他分享
首页 > 其他分享> > 【日常训练】20200304_T3_栅栏fence_平面图转对偶图/最小割树_HDU5518

【日常训练】20200304_T3_栅栏fence_平面图转对偶图/最小割树_HDU5518

作者:互联网

题面

给一张平面图,每条边有权值,一个环的权值为其每条边的权值和,求一个权值最小的环的集合使得所有环都能通过这个集合中的环异或得到。

题解

现场得分:30/30

这道题有点难写,因为我当时写了一个平面图转对偶图,还有一个特殊线性基。很长。不过竟然调对了。

代码

#include<bits/stdc++.h>
#define LL long long
#define U unsigned
#define eps 0.000001
#define MAXN 1010
#define INF 1000000000
using namespace std;
template<typename T> void Read(T &cn)
{
	char c; int sig = 1;
	while(!isdigit(c = getchar())) if(c == '-') sig = 0;
	if(sig) {cn = c-48; while(isdigit(c = getchar())) cn = cn*10-48+c; }
	else    {cn = 48-c; while(isdigit(c = getchar())) cn = cn*10+48-c; }
}
template<typename T> void Write(T cn)
{
	T cm = 0; int wei = 0, cx = cn%10; cn = cn/10;
	if(cn < 0 || cx < 0) {putchar('-'); cn = -cn; cx = -cx; }
	while(cn) wei++, cm = cm*10+cn%10, cn = cn/10;
	while(wei--) putchar(cm%10+48), cm = cm/10;
	putchar(cx+48);
}
template<typename T> void WriteL(T cn) {Write(cn); puts(""); }
template<typename T> void WriteS(T cn) {Write(cn); putchar(' '); }
template<typename T> void Max(T &cn, T cm) {cn = cn < cm ? cm : cn; }
template<typename T> void Min(T &cn, T cm) {cn = cn < cm ? cn : cm; }
struct Point{
	double x, y;
	void getit() {scanf("%lf %lf",&x,&y); }
	void mk(double cn, double cm) {x = cn; y = cm; }
	inline friend bool operator <(Point cn, Point cm) {return fabs(cn.x-cm.x)<=eps ? (fabs(cn.y-cm.y)<=eps ? 0 : cn.y < cm.y) : cn.x < cm.x; }
	inline friend Point operator -(Point cn, Point cm) {Point guo; guo.mk(cn.x-cm.x,cn.y-cm.y); return guo; }
};
struct Graph{
	struct qwe{
		int a,b,ne,yong,w;
		void mk(int cn, int cm, int cx, int cw) {a = cn; b = cm; ne = cx; w = cw; yong = 0; }
	};
	qwe a[MAXN*2+1];
	int alen;
	int head[MAXN+1];
	void lian(int cn, int cm, int cx) {a[++alen].mk(cn,cm,head[cn],cx); head[cn] = alen; }
	void liand(int cn, int cm, int cx) {lian(cn,cm,cx); lian(cm,cn,cx); }
	void build() {alen = 0; memset(head,0,sizeof(head)); }
};
struct Paixu{
	Point pos;
	int wei;
	void mk(Point cn, int cm) {pos = cn; wei = cm; }
};
double chaji(Point cn, Point cm) {return cn.x*cm.y-cm.x*cn.y; }
map<Point, int> M;
Point pos[MAXN+1];
int m, n1, n2, t;
Graph G1, G2;
int zhan[MAXN+1], zlen;
int ne[MAXN+1][MAXN+1], nelen[MAXN+1];
Paixu zhan2[MAXN+1];
int val[MAXN+1];
int get_Poi() {Point cn; cn.getit(); if(M.find(cn) == M.end()) M[cn] = ++n1, pos[n1] = cn; return M[cn]; }
int Cmp(Paixu cn, Paixu cm) 
{
	if(cn.wei == cm.wei) return 0;
	if(cn.pos.x == 0 && cn.pos.y<0) return 1;
	if(cm.pos.x == 0 && cm.pos.y<0) return 0;
	if(cn.pos.x == 0) return cm.pos.x < 0;
	if(cm.pos.x == 0) return cn.pos.x > 0;
	if(cn.pos.x > 0 && cm.pos.x < 0) return 1;
	if(cn.pos.x < 0 && cm.pos.x > 0) return 0;
	return chaji(cn.pos,cm.pos) > 0;
}
namespace Sub1{
	int pan() {return n2 >= 25 ? 0 : ((1<<n2)*G2.alen <= 40000000); }
	struct Jihe{
		int S, he;
		void mk(int cn, int cm) {S = cn; he = cm; }
		inline friend bool operator <(Jihe cn, Jihe cm) {return cn.he == cm.he ? cn.S < cm.S : cn.he < cm.he; }
	};
	struct Xxj{
		Jihe a[100];
		int n;
		LL he;
		void build(int cn) {n = cn; for(int i = 0;i<n;i++) a[i].mk(0,0); he = 0; }
		void cha(int cn, int cm)
		{
			for(int i = n-1;i>=0;i--) if(cn&(1<<i))
			{
				if(!a[i].S) {a[i].mk(cn, cm); he = he+cm; return; }
				cn = cn ^ a[i].S;
			}
		}
	}xxj;
	Jihe zhan[MAXN+1];
	int zlen;
	int fa[MAXN+1], you[MAXN+1];
	int get_fa(int cn) {return fa[cn] == cn ? cn : fa[cn] = get_fa(fa[cn]); }
	int main()
	{
		zlen = 0;
		for(int i = 1;i<(1<<n2);i++) 
		{
			for(int j = 1;j<=n2;j++) you[j] = (i&(1<<(j-1)))!=0;
			for(int j = 1;j<=n2;j++) fa[j] = j;
			int zong = 0;
			for(int j = 1;j<=n2;j++) if(you[j])
			{
				zong++;
				for(int ij = G2.head[j];ij;ij = G2.a[ij].ne) if(you[G2.a[ij].b] && get_fa(G2.a[ij].b) != get_fa(j))
				{
					zong--; fa[get_fa(G2.a[ij].b)] = get_fa(j);
				}
			}
			if(zong != 1) continue;
//			printf("i = %d\n",i);
//			for(int j = 1;j<=n2;j++) printf("you[%d] = %d\n",j,you[j]);
			LL lei = 0;
			for(int j = 1;j<=n2;j++) if(you[j])
			{
				for(int ij = G2.head[j];ij;ij = G2.a[ij].ne) if(you[G2.a[ij].b]) lei = lei + G2.a[ij].w;
			}
//			printf("lei = %lld\n",lei);
			lei = -lei;
			for(int j = 1;j<=n2;j++) if(you[j]) lei = lei + val[j];
//			printf("lei = %lld\n",lei);
			zhan[++zlen].mk(i, lei);
		}
		sort(zhan+1, zhan+zlen+1);
		xxj.build(n2);
		for(int i = 1;i<=zlen;i++) xxj.cha(zhan[i].S, zhan[i].he);
		WriteL(xxj.he);
		return 0;
	}
}
namespace Sub2{
	Graph G;
	struct Flow{
		int shen[MAXN+1], lst[MAXN+1], dui[MAXN+1];
		LL ans;
		int bfs(int cn, int cm, int ctot)
		{
			for(int i = 1;i<=ctot;i++) shen[i] = ctot+1, lst[i] = G2.head[i];
			int l = 0, r = 0; dui[++r] = cn; shen[cn] = 0;
			while(l < r)
			{
				int dang = dui[++l];
				for(int i = G2.head[dang];i;i = G2.a[i].ne)
				{
					int y = G2.a[i].b;
					if(G2.a[i].w == 0 || shen[y] <= shen[dang]+1) continue;
					shen[y] = shen[dang]+1; dui[++r] = y;
				}
			}
			return shen[cm] != ctot+1;
		}
		int dfs(int cn, int cm, int liu)
		{
			if(cn == cm) {ans = ans + liu; return liu; }
			for(int &i = lst[cn];i;i = G2.a[i].ne)
			{
				int y = G2.a[i].b;
				if(G2.a[i].w == 0 || shen[y] != shen[cn]+1) continue;
				int lin = dfs(y, cm, min(liu, G2.a[i].w));
				if(lin) {
					G2.a[i].w -= lin; G2.a[((i-1)^1)+1].w += lin; return lin;
				}
			}
			return 0;
		}
		void sou_fen(int cn, int fen[])
		{
			if(fen[cn]) return; fen[cn] = 1;
			for(int i = G2.head[cn];i;i = G2.a[i].ne) if(G2.a[i].w) sou_fen(G2.a[i].b, fen);
		}
		LL flow(int cn, int cm, int ctot, int fen[])
		{
			ans = 0;
			while(bfs(cn,cm,ctot)) while(dfs(cn,cm,INF));
			for(int i = 1;i<=ctot;i++) fen[i] = 0;
			sou_fen(cn, fen);
			return ans;
		}
	}W;
	int zhan[MAXN+1], zhan2[MAXN+1], zlen;
	int fen[MAXN+1];
	LL ans;
	void sou(int cl, int cr)
	{
//		printf("in sou : cl = %d cr = %d\n",cl,cr);
		if(cl == cr) return;
		for(int i = 1;i<=G2.alen;i++) G.a[i].w = G2.a[i].w;
		int lin = W.flow(zhan[cl], zhan[cr], n2, fen);
		for(int i = 1;i<=G2.alen;i++) G2.a[i].w = G.a[i].w;
		ans = ans + lin;
//		printf("lin = %d\n",lin);
//		for(int i = 1;i<=n2;i++) printf("fen[%d] = %d\n",i,fen[i]);
		zlen = 0; for(int i = cl;i<=cr;i++) if(fen[zhan[i]]) zhan2[++zlen] = zhan[i];
		int geshu = cl+zlen-1;
		for(int i = cl;i<=cr;i++) if(!fen[zhan[i]]) zhan2[++zlen] = zhan[i];
		for(int i = cl;i<=cr;i++) zhan[i] = zhan2[i-cl+1];
		sou(cl, geshu); sou(geshu+1, cr);
	}
	int main()
	{
		for(int i = 1;i<=n2;i++) zhan[i] = i; ans = 0;
		sou(1, n2);
		WriteL(ans);
		return 0;
	}
}
int zuo()
{
	Read(m);
	M.clear(); G1.build(); G2.build();
	n1 = n2 = 0;
	for(int i = 1;i<=m;i++)
	{
		int bx = get_Poi(), by = get_Poi();
		int bz; Read(bz); 
		G1.liand(bx,by,bz);
	}
//	for(int i = 1;i<=n1;i++) printf("%d : (%.0lf %.0lf)\n",i,pos[i].x,pos[i].y);
//	for(int i = 1;i<=G1.alen;i++) printf("G1 : %d : (%d -> %d) %d\n",i,G1.a[i].a,G1.a[i].b,G1.a[i].w);
	for(int i = 1;i<=n1;i++)
	{
		nelen[i] = 0;
		for(int j = G1.head[i];j;j = G1.a[j].ne) zhan2[++nelen[i]].mk(pos[G1.a[j].b]-pos[i], j);
		sort(zhan2+1, zhan2+nelen[i]+1, Cmp);
		for(int j = 1;j<=nelen[i];j++) ne[i][j] = zhan2[j].wei;
//		for(int j = 1;j<=nelen[i];j++) printf("ne[%d][%d] = %d\n",i,j,ne[i][j]);
	}
	for(int i = 1;i<=G1.alen;i++) if(!G1.a[i].yong)
	{
//		printf("i = %d (%d, %d)\n",i,G1.a[i].a,G1.a[i].b);
		zlen = 0; int xian = G1.a[i].b, lst = G1.a[i].a;
		zhan[++zlen] = i;
		while(xian != G1.a[i].a) 
		{
			int nxt = 0;
			for(int j = 1;j<=nelen[xian];j++) if(G1.a[ne[xian][j]].b == lst) nxt = j;
			if(nxt == 1) nxt = ne[xian][nelen[xian]];
			else nxt = ne[xian][nxt-1];
			zhan[++zlen] = nxt; lst = xian; xian = G1.a[nxt].b;
		}
		double he = 0;
		Point yuan = pos[G1.a[zhan[1]].a];
		for(int j = 1;j<=zlen;j++) he = he + chaji(pos[G1.a[zhan[j]].a]-yuan, pos[G1.a[zhan[j]].b]-yuan);
//		for(int j = 1;j<=zlen;j++) printf("zhan[%d] = %d (%d->%d)\n",j,zhan[j],G1.a[zhan[j]].a,G1.a[zhan[j]].b);
		if(he < 0) for(int j = 1;j<=zlen;j++) G1.a[zhan[j]].yong = -1;
		else {
			n2++; val[n2] = 0; 
			for(int j = 1;j<=zlen;j++) G1.a[zhan[j]].yong = n2, val[n2] += G1.a[zhan[j]].w;
		}
	}
	n2++; val[n2] = 0;
	for(int i = 1;i<=G1.alen;i++) if(G1.a[i].yong == -1) G1.a[i].yong = n2;
	for(int i = 1;i<=G1.alen;i+=2) if(G1.a[i].yong > 0 && G1.a[i+1].yong > 0) G2.liand(G1.a[i].yong, G1.a[i+1].yong, G1.a[i].w);
//	for(int i = 1;i<=G2.alen;i++) printf("G2 : %d : (%d -> %d) %d\n",i,G2.a[i].a,G2.a[i].b,G2.a[i].w);
//	for(int i = 1;i<=n2;i++) printf("val[%d] = %d\n",i,val[i]);
//	if(Sub1::pan()) return Sub1::main();
	return Sub2::main();
}
signed main()
{
	freopen("fence.in","r",stdin);
	freopen("fence.out","w",stdout);
	Read(t); for(int i = 1;i<=t;i++) printf("Case #%d: ",i), zuo();
	return 0;
}
/*
2
5
0 0 0 1 1
0 0 1 0 1
0 1 1 1 1
1 0 1 1 1
1 0 0 1 100
9
1 1 3 1 1
1 1 1 3 2
3 1 3 3 2
1 3 3 3 1
1 1 2 2 2
2 2 3 3 3
3 1 2 2 1
2 2 1 3 2
4 1 5 1 4

1
12
1 1 2 1 1
1 1 2 2 2
1 1 2 3 1
2 1 2 2 1
2 2 2 3 1
2 1 3 1 1
2 1 3 2 1
2 2 3 2 1
2 3 3 2 1
2 3 3 3 1
3 1 3 2 1
3 2 3 3 1
*/

标签:10,HDU5518,cn,cm,20200304,int,pos,G1,fence
来源: https://www.cnblogs.com/czyarl/p/14483555.html