朱刘算法

前言

这只是一个用来存板子的地方
貌似这个东西除了做板题就没用了

练习

板题1(洛谷)

板题2(POJ)

代码

板题1代码

struct edge
{
	int u,v,w;
	edge(){}
	edge(int u1,int v1,int w1){
		u = u1;
		v = v1;
		w = w1;
	}
}e[MAXM];

int in[MAXN],pre[MAXN],vis[MAXN],ID[MAXN];
int zhuliu()
{
	int ret = 0;
	while(1)
	{
		for(int i = 1;i <= n;++ i) in[i] = INF;
		for(int i = 1;i <= m;++ i)
			if(e[i].w < in[e[i].v])
				in[e[i].v] = e[i].w,pre[e[i].v] = e[i].u;
		for(int i = 1;i <= n;++ i) if(i != rt && in[i] == INF) return -1;
		int cnt = 0,tmp = 0;
		for(int i = 1;i <= n;++ i) vis[i] = ID[i] = 0;
		for(int i = 1;i <= n;++ i)
		{
			if(i == rt) continue;
			ret += in[i];
			int now = i;
			while(vis[now] != i && !ID[now] && now != rt)
			{
				vis[now] = i;
				now = pre[now];
			}
			if(!ID[now] && now != rt)
			{
				ID[now] = ++cnt;
				while(!ID[pre[now]]) now = pre[now],ID[now] = cnt;
			}
		}
		if(!cnt) break;//无环 
		for(int i = 1;i <= n;++ i) if(!ID[i]) ID[i] = ++cnt;//不是环上的点 
		for(int i = 1;i <= m;++ i)
			if(ID[e[i].u] != ID[e[i].v])
				e[++tmp] = edge(ID[e[i].u],ID[e[i].v],e[i].w - in[e[i].v]);
		rt = ID[rt];
		n = cnt;
		m = tmp;
	}
	return ret;
}

int main()
{
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	n = Read(); m = Read(); rt = Read();
	for(int i = 1;i <= m;++ i) 
	{
		e[i].u = Read();
		e[i].v = Read();
		e[i].w = Read();
		if(e[i].u == e[i].v) m--,i--;
	}
	Put(zhuliu());
	return 0;
}

板题2代码
用快读要T,真就用脚造数据?

struct edge
{
	int u,v;
	double w;
	edge(){}
	edge(int u1,int v1,double w1){
		u = u1;
		v = v1;
		w = w1;
	}
}e[MAXM];
struct node
{
	int x,y;
}p[MAXN];

double dis(node a,node b) {return sqrt(1.0 * (a.x - b.x) * (a.x - b.x) + 1.0 * (a.y - b.y) * (a.y - b.y));}

int pre[MAXN],vis[MAXN],ID[MAXN];
double in[MAXN];
double zhuliu()
{
	double ret = 0;
	while(1)
	{
		for(int i = 1;i <= n;++ i) in[i] = INF;
		for(int i = 1;i <= m;++ i)
			if(e[i].w < in[e[i].v])
				in[e[i].v] = e[i].w,pre[e[i].v] = e[i].u;
		for(int i = 1;i <= n;++ i) if(i != rt && in[i] == INF) return -1;
		int cnt = 0,tmp = 0;
		for(int i = 1;i <= n;++ i) vis[i] = ID[i] = 0;
		for(int i = 1;i <= n;++ i)
		{
			if(i == rt) continue;
			ret += in[i];
			int now = i;
			while(vis[now] != i && !ID[now] && now != rt)
			{
				vis[now] = i;
				now = pre[now];
			}
			if(!ID[now] && now != rt)
			{
				ID[now] = ++cnt;
				while(!ID[pre[now]]) now = pre[now],ID[now] = cnt;
			}
		}
		if(!cnt) break;
		for(int i = 1;i <= n;++ i) if(!ID[i]) ID[i] = ++cnt;
		for(int i = 1;i <= m;++ i)
			if(ID[e[i].u] != ID[e[i].v])
				e[++tmp] = edge(ID[e[i].u],ID[e[i].v],e[i].w - in[e[i].v]);
		rt = ID[rt];
		n = cnt;
		m = tmp;
	}
	return ret;
}

int main()
{
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	while(~scanf("%d %d",&n,&m))
	{
		rt = 1;
		for(int i = 1;i <= n;++ i) scanf("%d %d",&p[i].x,&p[i].y);
		for(int i = 1;i <= m;++ i) 
		{
			scanf("%d %d",&e[i].u,&e[i].v);
			if(e[i].u == e[i].v) m--,i--;
			else e[i].w = dis(p[e[i].u],p[e[i].v]);
		}
		double ans = zhuliu();
		if(ans == -1) printf("poor snoopy\n");
		else printf("%.2f\n",ans);
	}
	return 0;
}
posted @ 2020-09-23 15:13  皮皮刘  阅读(124)  评论(0编辑  收藏  举报