首页 > 其他分享 >2417. 指挥网络

2417. 指挥网络

时间:2022-12-04 23:12:29浏览次数:55  
标签:利特 电线 le int 网络 指挥 2417 节点 define

题目链接

2417. 指挥网络

在漫长的骂战过后,利特肯王国和克努斯海洋王国之间爆发了一场武装战争。

克努斯海洋王国部队的猛烈进攻使得利特肯王国的指挥网络彻底瘫痪

临时指挥网络的建立刻不容缓。

利特肯命令史努比负责该项目。

利特肯王国共有 \(N\) 个指挥部,位于平面中的 \(N\) 个节点上(编号 \(1 \sim N\))。

其中利特肯所在的指挥总部位于节点 \(1\)。

通过对战时情况的详尽研究,史努比认为,当前最关键的一点在于建立一个单向通信网络,使得利特肯的命令能够成功传达至平面中的每个节点处。

如果希望利特肯的命令能够直接从节点 \(A\) 传递到另一个节点 \(B\),则必须沿着连接两个节点的直线段构建一条单向传输电线。

因为战争还未停止,所以并不是所有节点对之间都能建立电线。(甚至能够建立从节点 \(A\) 传递消息至节点 \(B\) 的电线,也不一定能够建立从节点 \(B\) 传递消息至节点 \(A\) 的电线)

史努比希望这项工程所需耗费的电线长度尽可能短,以便施工可以尽快完成。

输入格式

输入包含若干测试数据。

每组数据第一行包含两个整数 \(N,M\),表示节点总数以及可在其间建立电线的节点对数。

接下来 \(N\) 行,其中第 \(i\) 行包含两个整数 \(x_i,y_i\),表示节点 \(i\) 的位置坐标为 \((x_i,y_i)\)。

接下来 \(M\) 行,每行包含两个整数 \(a,b\),表示可以建立一条单向电线使得命令可以从节点 \(a\) 传递至节点 \(b\)。

处理至文件末尾。

输出格式

对于每个测试数据,输出结果占一行。

如果临时网络可以成功构建,则输出所需耗费电线的最小可能长度,保留两位小数。

如果不能成功构建,则输出 poor snoopy

数据范围

\(1 \le N \le 100\),
\(1 \le M \le 10^4\),
\(0 \le x_i,y_i \le 10^5\),
\(1 \le a,b \le N\),\(a \neq b\),
每个输入最多包含 \(10\) 组测试。

输入样例:

4 6
0 6
4 6
0 0
7 20
1 2
1 3
2 3
3 4
3 1
3 2
4 3
0 0
1 0
0 1
1 2
1 3
4 1
2 3

输出样例:

31.19
poor snoopy

解题思路

朱刘算法,最小树形图

树形图:对于有向图而言,其无环,且除根外的所有点的入度都为 \(1\)

朱刘算法主要用来求解有向图的最小树形图,即总权值最小的树形图
算法流程:对于每个点都找一条权值最小的指向该点的边,如果这样的边不能构成一个环的话,则说明找到答案,结束整个算法流程,否则缩点,对于某条指向该缩点的边,其权值需要再减去其指向缩点表示的环的点的前驱边的权值,然后继续找出这样的边,直到没有环出现
证明略

  • 时间复杂度:\(O(nm)\)

代码

// Problem: 指挥网络
// Contest: AcWing
// URL: https://www.acwing.com/problem/content/2419/
// Memory Limit: 64 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

// %%%Skyqwq
#include <bits/stdc++.h>
 
//#define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
 
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
 
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
 
template <typename T> void inline read(T &x) {
    int f = 1; x = 0; char s = getchar();
    while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
    while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
    x *= f;
}

typedef pair<double,double> PDD;
const int N=105;
const double inf=1e9;
int n,m;
bool g[N][N],st[N];
PDD a[N];
double d[N][N],bd[N][N];
int pre[N];
int dfn[N],low[N],scc_cnt,id[N],timestamp,stk[N],top;
bool in_stk[N];
void dfs(int x)
{
	st[x]=true;
	for(int i=1;i<=n;i++)
		if(g[x][i]&&!st[i])dfs(i);
}
bool check_con()
{
	memset(st,0,sizeof st);
	dfs(1);
	for(int i=1;i<=n;i++)
		if(!st[i])return false;
	return true;
}
double get_dist(int x,int y)
{
	double dx=a[x].fi-a[y].fi;
	double dy=a[x].se-a[y].se;
	return sqrt(dx*dx+dy*dy);
}
void tarjan(int x)
{
	dfn[x]=low[x]=++timestamp;
	stk[++top]=x,in_stk[x]=true;
	int y=pre[x];
	if(!dfn[y])
	{
		tarjan(y);
		low[x]=min(low[x],low[y]);
	}
	else if(in_stk[y])low[x]=min(low[x],dfn[y]);
	if(low[x]==dfn[x])
	{
		int y;
		scc_cnt++;
		do
		{
			y=stk[top--];
			in_stk[y]=false;
			id[y]=scc_cnt;
		}while(y!=x);
	}
}
double work()
{
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			if(g[i][j])d[i][j]=get_dist(i,j);
			else
				d[i][j]=inf;
	double res=0;
	while(true)
	{
		for(int i=1;i<=n;i++)
		{
			pre[i]=i;
			for(int j=1;j<=n;j++)
				if(d[pre[i]][i]>d[j][i])
					pre[i]=j;
		}
		memset(dfn,0,sizeof dfn);
		scc_cnt=timestamp=top=0;
		for(int i=1;i<=n;i++)
			if(!dfn[i])tarjan(i);
		if(scc_cnt==n)
		{
			for(int i=2;i<=n;i++)res+=d[pre[i]][i];
			break;
		}
		for(int i=2;i<=n;i++)
			if(id[i]==id[pre[i]])res+=d[pre[i]][i];
		for(int i=1;i<=scc_cnt;i++)
			for(int j=1;j<=scc_cnt;j++)
				bd[i][j]=inf;
		for(int i=1;i<=n;i++)
			for(int j=1;j<=n;j++)
				if(d[i][j]<inf&&id[i]!=id[j])
				{
					int x=id[i],y=id[j];
					if(id[pre[j]]==id[j])
						bd[x][y]=min(bd[x][y],d[i][j]-d[pre[j]][j]);
					else
						bd[x][y]=min(bd[x][y],d[i][j]);
				}
		n=scc_cnt;
		memcpy(d,bd,sizeof bd);
	}
	return res;
}
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
    	memset(g,0,sizeof g);
    	for(int i=1;i<=n;i++)scanf("%lf%lf",&a[i].fi,&a[i].se);
	    for(int i=1;i<=m;i++)
	    {
	    	int x,y;
	    	scanf("%d%d",&x,&y);
	    	if(x!=y&&y!=1)g[x][y]=true;
	    }
	    if(!check_con())puts("poor snoopy");
	    else
	    	printf("%.2lf\n",work());
    }
    return 0;
}

标签:利特,电线,le,int,网络,指挥,2417,节点,define
From: https://www.cnblogs.com/zyyun/p/16951136.html

相关文章

  • 漫谈计算机网络:应用层 ----- 从DNS域名解析到WWW万维网再到P2P应用
    2022-12-0418:31:01纪念一下博主的《漫谈计算机网络》连载博客浏览量破500了!今天更新完结篇!面试答不上?计网很枯燥?听说你学习计网每次记了都会忘?不妨抽时间和我......
  • C#网络编程之TCP(六)
    一、大文件的上传上一章节我们了解了小文件在客户端和服务器之间是如何传输的。但对于一个几百兆或者几个G大文件来说,无法通过一次传送,就能够把文件的所有数据都传过......
  • 网络通信中的粘包问题
    什么是粘包?在网络传输层有TCP和UDP两种协议;如果使用TCP进行通信,则在大多数场景下是不存在丢包和包乱序问题的,因为TCP通信是可靠的通信方式,TCP栈通过序列号和包重传确认机......
  • 网络性能监控工具整理
    提纲netperfiperfpathcharntttcpitracertnetperfnetperf是一款针对网络性能的测试工具,主要基于TCP或UDP的传输。根据应用的不同,可以进行批量数据传输(bulkdatat......
  • 无线网有限的权限访问,本地连接已启用但也没网络(奋战8小时解决)
    起因:头一天正常使用,第二天开机发现台式的无线网(USB接口)连接网络提示有限的权限访问经过:1.重新断开连接无效2.重新启动路由器无效3.重新插板网卡无效4.禁用启用网卡无......
  • 《wireshark网络分析就这么简单》总结
     《从一到面试题开始说起》、《小试牛刀:一个简单的应用实例》、《excel文件的保存过程》、《你一定会喜欢的技巧》(tcpdump抓包技巧)、《NFS协议的解析》==============......
  • 在 Linux 命令行中使用 tcpdump 命令分析网络数据
    在Linux命令行中使用tcpdump命令分析网络数据该文章作者是刘光录,TIAP收录于合集#Linux143个tcpdump 是分析网络和排查网络问题的一个很好用的工具,它通过抓取数据包,显......
  • 网络编程
    IP地址ip地址:inetAddress127.0.0.1:本机localhostip地址分类:ipv4/ipv6公网(互联网)-私网(局域网)ABCD类地址192.168.xx.xx专门给组织用域名:记忆ip端口port......
  • 详解cycleGAN(生成对抗网络)代码
    文章目录​​1.cycleGAN简介​​​​2.cycle代码详解​​​​main.py​​​​module.py​​​​model.py​​​​总结​​1.cycleGAN简介关于cGAN我主要参考了知乎量子位的......
  • 深度学习基础课:卷积神经网络与卷积层的前向传播推导
    大家好~本课程为“深度学习基础班”的线上课程,带领同学从0开始学习全连接和卷积神经网络,进行数学推导,并且实现可以运行的Demo程序线上课程资料:本节课录像回放1加QQ群,获......