防爆秃击队——最短路/最小生成树专题(一)

//第一次的专题AK(当然搜了一下思路2333)
在这里插入图片描述

A - Til the Cows Come Home

1.题目描述:
Bessie is out in the field and wants to get back to the barn to get as much sleep as possible before Farmer John wakes her for the morning milking. Bessie needs her beauty sleep, so she wants to get back as quickly as possible.

Farmer John’s field has N (2 <= N <= 1000) landmarks in it, uniquely numbered 1…N. Landmark 1 is the barn; the apple tree grove in which Bessie stands all day is landmark N. Cows travel in the field using T (1 <= T <= 2000) bidirectional cow-trails of various lengths between the landmarks. Bessie is not confident of her navigation ability, so she always stays on a trail from its start to its end once she starts it.

Given the trails between the landmarks, determine the minimum distance Bessie must walk to get back to the barn. It is guaranteed that some such route exists.
Input

  • Line 1: Two integers: T and N

  • Lines 2…T+1: Each line describes a trail as three space-separated integers. The first two integers are the landmarks between which the trail travels. The third integer is the length of the trail, range 1…100.
    Output

  • Line 1: A single integer, the minimum distance that Bessie must travel to get from landmark N to landmark 1.
    Sample Input
    5 5
    1 2 20
    2 3 30
    3 4 20
    4 5 20
    1 5 100
    Sample Output
    90
    Hint
    INPUT DETAILS:

There are five landmarks.

OUTPUT DETAILS:

Bessie can get home by following trails 4, 3, 2, and 1.

2.题意:一头牛吧好像是,想回到农场,因为狂欢了一整晚,想要以最快的速度回到农场。

3.思路:
最短路问题模板题。 最短时间嘛,无负权,直接dijkstra就好了。

4.代码:

//A - Til the Cows Come Home
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#define FAST ios::sync_with_stdio(false)
#define mem(a,b) memset(a,b,sizeof(a))
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define rep(i,a,n) for(int i=a;i<n;++i)
#define per(i,a,n) for(int i=n-1,i>=a;--i)
using namespace std;
typedef long long ll;
const int maxn = 1000+5;
const int inf=0x3f3f3f3f;
const double eps = 1e-7;
inline int lowbit(int x){return x&(-x);}
inline int read()
{
	int x=0,sign=1;
	char c=getchar();
	while(c>'9'||c<'0') {if(c=='-') sign=-1;c=getchar();}
	while('0'<=c&&c<='9') x=x*10+c-'0',c=getchar();
	return x*sign;
}
//head
int head[maxn],cnt;
int n,m,u,v,d;
struct Edge
{
	int v,w,nx;
}edge[maxn<<2];
inline void add(int u,int v,int w)
{
	edge[++cnt]=(Edge){v,w,head[u]};
	head[u]=cnt;
}
struct node
{
	int u,w;
	bool operator <(const node& x)const{return w>x.w;}
};
//
bool vis[maxn];
int dis[maxn];
inline int Dij(int s,int e)
{
	priority_queue<node> q;
	dis[s]=0;
	q.push((node){s,dis[s]});
	while(!q.empty())
	{
		node tmp=q.top();q.pop();
		u=tmp.u;
		if(vis[u]) continue;
		vis[u]=true;
		for(int i=head[u];i;i=edge[i].nx)
		{
			v=edge[i].v;
			d=edge[i].w;
			if(dis[v]>dis[u]+d)
			{
				dis[v]=dis[u]+d;
				q.push((node){v,dis[v]});
			}
		}
	}
	return dis[e];
}
inline void init()
{
	cnt=0;
	mem(head,0);
	mem(vis,0);
	mem(dis,inf);
}
inline void solve()
{
	init();
	while(m--)
	{
		u=read(),v=read(),d=read();
		add(u,v,d),add(v,u,d);
	}
	printf("%d",Dij(n,1));
	puts("");
}
int main()
{
	//freopen("C:\\Users\\Administrator\\Desktop\\in.txt","r",stdin);
	while(~scanf("%d%d",&m,&n)) solve();
	return 0;
}

B - Frogger

1.题目描述:
Freddy Frog is sitting on a stone in the middle of a lake. Suddenly he notices Fiona Frog who is sitting on another stone. He plans to visit her, but since the water is dirty and full of tourists’ sunscreen, he wants to avoid swimming and instead reach her by jumping.
Unfortunately Fiona’s stone is out of his jump range. Therefore Freddy considers to use other stones as intermediate stops and reach her by a sequence of several small jumps.
To execute a given sequence of jumps, a frog’s jump range obviously must be at least as long as the longest jump occuring in the sequence.
The frog distance (humans also call it minimax distance) between two stones therefore is defined as the minimum necessary jump range over all possible paths between the two stones.

You are given the coordinates of Freddy’s stone, Fiona’s stone and all other stones in the lake. Your job is to compute the frog distance between Freddy’s and Fiona’s stone.
Input
The input will contain one or more test cases. The first line of each test case will contain the number of stones n (2<=n<=200). The next n lines each contain two integers xi,yi (0 <= xi,yi <= 1000) representing the coordinates of stone #i. Stone #1 is Freddy’s stone, stone #2 is Fiona’s stone, the other n-2 stones are unoccupied. There’s a blank line following each test case. Input is terminated by a value of zero (0) for n.
Output
For each test case, print a line saying “Scenario #x” and a line saying “Frog Distance = y” where x is replaced by the test case number (they are numbered from 1) and y is replaced by the appropriate real number, printed to three decimals. Put a blank line after each test case, even after the last one.
Sample Input
2
0 0
3 4

3
17 4
19 4
18 5

0
Sample Output
Scenario #1
Frog Distance = 5.000

Scenario #2
Frog Distance = 1.414

2.题意:
一只青蛙想到另一只青蛙那,但是他们隔得太远了,所以青蛙想借助其他东西跳过去,问它所需要跳过去的最短的最大距离是多少?

3.思路:
这个是求:最小的最大距离,听着有点绕啊,其实就是什么呢,它希望这个一条路径中最大的那条边尽可能小。那么我们怎么做呢,我们可以直接用dij算法变形一下或者用spfa也行。具体是怎么变形呢,dis数组的含义变为:到达这个点的路径的最小的最大值。 我们依然是找最小的那一条路径,因为这样最大距离才有可能最小嘛,不过我们松弛操作就要变成:dis[v]>max(dis[u],G[u][v]) 这个意义也很简单:就是我们如果到达v这个点路途中的最小的最大值要比到达u这个点和u到v的边的最大值都要大的话,那么我们当然先走u再到v,这样可以使得最大边值尽可能小。

4.代码:

//B - Frogger
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#define FAST ios::sync_with_stdio(false)
#define mem(a,b) memset(a,b,sizeof(a))
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define rep(i,a,n) for(int i=a;i<n;++i)
#define per(i,n,a) for(int i=n-1;i>=a;--i)
using namespace std;
typedef long long ll;
const int maxn = 200+5;
const int maxm = 500000+5;
const int inf=0x3f3f3f3f;
const double eps = 1e-7;
inline int lowbit(int x){return x&(-x);}
inline int gcd(int a,int b){return b?gcd(b,a%b):a;}
inline int read()
{
	int x=0,sign=1;
	char c=getchar();
	while(c>'9'||c<'0') {if(c=='-') sign=-1;c=getchar();}
	while('0'<=c&&c<='9') x=x*10+c-'0',c=getchar();
	return x*sign;
}
//head
int n,m;
double G[maxn][maxn];
struct Point
{
	int x,y;
}point[maxm],s,e;
inline double w(Point a,Point b)
{
	return sqrt((double)(a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
double dis[maxn];
bool vis[maxn];
double Dij(int s,int e)
{
	rep(i,0,n)
	{
		dis[i]=G[s][i];
		vis[i]=0;
	}
	vis[s]=1;
	int k=0;
	rep(i,0,n)
	{
		double minn=inf;
		rep(j,0,n)
			if(!vis[j]&&minn>dis[j])
				minn=dis[j],k=j;
		vis[k]=1;
		rep(j,0,n)
			if(dis[j]>max(dis[k],G[k][j]))
				dis[j]=max(dis[k],G[k][j]);
	}
	return dis[e];
}
inline void solve()
{
	rep(i,0,n) point[i].x=read(),point[i].y=read();
	rep(i,0,n) rep(j,0,n) G[i][j]=w(point[i],point[j]);
	double ans=Dij(0,1);
	printf("Frog Distance = %.3f\n",ans);
	puts("");
}
int main()
{
	//freopen("C:\\Users\\Administrator\\Desktop\\in.txt","r",stdin);
	int t=0;
	while(scanf("%d",&n)&&n)
	{
		printf("Scenario #%d\n",++t);
		solve();
	}
	return 0;
}

C - Jungle Roads

1.题目描述:
在这里插入图片描述

The Head Elder of the tropical island of Lagrishan has a problem. A burst of foreign aid money was spent on extra roads between villages some years ago. But the jungle overtakes roads relentlessly, so the large road network is too expensive to maintain. The Council of Elders must choose to stop maintaining some roads. The map above on the left shows all the roads in use now and the cost in aacms per month to maintain them. Of course there needs to be some way to get between all the villages on maintained roads, even if the route is not as short as before. The Chief Elder would like to tell the Council of Elders what would be the smallest amount they could spend in aacms per month to maintain roads that would connect all the villages. The villages are labeled A through I in the maps above. The map on the right shows the roads that could be maintained most cheaply, for 216 aacms per month. Your task is to write a program that will solve such problems.

The input consists of one to 100 data sets, followed by a final line containing only 0. Each data set starts with a line containing only a number n, which is the number of villages, 1 < n < 27, and the villages are labeled with the first n letters of the alphabet, capitalized. Each data set is completed with n-1 lines that start with village labels in alphabetical order. There is no line for the last village. Each line for a village starts with the village label followed by a number, k, of roads from this village to villages with labels later in the alphabet. If k is greater than 0, the line continues with data for each of the k roads. The data for each road is the village label for the other end of the road followed by the monthly maintenance cost in aacms for the road. Maintenance costs will be positive integers less than 100. All data fields in the row are separated by single blanks. The road network will always allow travel between all the villages. The network will never have more than 75 roads. No village will have more than 15 roads going to other villages (before or after in the alphabet). In the sample input below, the first data set goes with the map above.

The output is one integer per line for each data set: the minimum cost in aacms per month to maintain a road system that connect all the villages. Caution: A brute force solution that examines every possible set of roads will not finish within the one minute time limit.
Input
9
A 2 B 12 I 25
B 3 C 10 H 40 I 8
C 2 D 18 G 55
D 1 E 44
E 2 F 60 G 38
F 0
G 1 H 35
H 1 I 35
3
A 2 B 10 C 40
B 1 C 20
0
Output
216
30
Sample Input
9
A 2 B 12 I 25
B 3 C 10 H 40 I 8
C 2 D 18 G 55
D 1 E 44
E 2 F 60 G 38
F 0
G 1 H 35
H 1 I 35
3
A 2 B 10 C 40
B 1 C 20
0
Sample Output
216
30

2.题意:
大概说,有一个村落,村庄之间彼此有公路连接,公路维护需要费用,求最小花费的能把村庄都连通的花费。翻译语言:这个有一个连通图,然后求最小权值和的极小连通图。

3.思路:
最小生成树模板题。 这题直接Krusual或者Prim都行,但是推荐前者,因为比较快。

4.代码:

//C - Jungle Roads
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#define FAST ios::sync_with_stdio(false)
#define mem(a,b) memset(a,b,sizeof(a))
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define rep(i,a,n) for(int i=a;i<n;++i)
#define per(i,n,a) for(int i=n-1;i>=a;--i)
using namespace std;
typedef long long ll;
const int maxn = 26+5;
const int maxm = 100+5;
const int inf=0x7fffffff;
const double eps = 1e-7;
inline int lowbit(int x){return x&(-x);}
int gcd(int a,int b){return b?gcd(b,a%b):a;}
inline int read()
{
	int x=0,sign=1;
	char c=getchar();
	while(c>'9'||c<'0') {if(c=='-') sign=-1;c=getchar();}
	while('0'<=c&&c<='9') x=x*10+c-'0',c=getchar();
	return x*sign;
}
//head
int n,m;
int par[maxn];
int f(int x){return x==par[x]?x:par[x]=f(par[x]);}
struct node
{
	int u,v,w;
	bool operator <(const node& a)const
	{
		return w>a.w;
	}
};
priority_queue<node> q;
int k;
inline void solve()
{
	char u=getchar(),v;
	rep(i,1,n+1) par[i]=i;
	rep(i,0,n-1)
	{
		u=getchar();
		k=read();
		if(!k) continue;
		while(k--)
		{
			v=getchar();
			int x=read();
			q.push((node){u-'A'+1,v-'A'+1,x});
		}
	}
	int res=0;
	while(!q.empty())
	{
		node tmp=q.top();q.pop();
		int fu=f(tmp.u),fv=f(tmp.v);
		if(fu!=fv)
		{
			res+=tmp.w;
			par[fv]=fu;
		}
	}
	printf("%d",res);
	puts("");
}
int main()
{
	//freopen("C:\\Users\\Administrator\\Desktop\\in.txt","r",stdin);
	while(scanf("%d",&n)&&n) solve();
	return 0;
}

D - Agri-Net

1.题目描述:
Farmer John has been elected mayor of his town! One of his campaign promises was to bring internet connectivity to all farms in the area. He needs your help, of course.
Farmer John ordered a high speed connection for his farm and is going to share his connectivity with the other farmers. To minimize cost, he wants to lay the minimum amount of optical fiber to connect his farm to all the other farms.
Given a list of how much fiber it takes to connect each pair of farms, you must find the minimum amount of fiber needed to connect them all together. Each farm must connect to some other farm such that a packet can flow from any one farm to any other farm.
The distance between any two farms will not exceed 100,000.
Input
The input includes several cases. For each case, the first line contains the number of farms, N (3 <= N <= 100). The following lines contain the N x N conectivity matrix, where each element shows the distance from on farm to another. Logically, they are N lines of N space-separated integers. Physically, they are limited in length to 80 characters, so some lines continue onto others. Of course, the diagonal will be 0, since the distance from farm i to itself is not interesting for this problem.
Output
For each case, output a single integer length that is the sum of the minimum length of fiber required to connect the entire set of farms.
Sample Input
4
0 4 9 21
4 0 8 17
9 8 0 16
21 17 16 0
Sample Output
28

2.题意:
大概说的是,建公路把农场全都连起来,然后求最低的花费。

3.思路:
最小生成树模板题。 推荐Prim,因为给好了矩阵,实现方便。

4.代码:

//D - Agri-Net
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#define FAST ios::sync_with_stdio(false)
#define mem(a,b) memset(a,b,sizeof(a))
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define rep(i,a,n) for(int i=a;i<n;++i)
#define per(i,n,a) for(int i=n-1;i>=a;--i)
using namespace std;
typedef long long ll;
const int maxn = 100+5;
const int maxm = 100000+5;
const int inf=0x3f3f3f3f;
const double eps = 1e-7;
inline int lowbit(int x){return x&(-x);}
inline int gcd(int a,int b){return b?gcd(b,a%b):a;}
inline int read()
{
	int x=0,sign=1;
	char c=getchar();
	while(c>'9'||c<'0') {if(c=='-') sign=-1;c=getchar();}
	while('0'<=c&&c<='9') x=x*10+c-'0',c=getchar();
	return x*sign;
}
//head
int n,res;
int G[maxn][maxn];
int dis[maxn];
int vis[maxn];
void Prim()
{
	rep(i,1,n+1)
	{
		dis[i]=G[1][i];
		vis[i]=0;
	}
	vis[1]=1;
	rep(i,2,n+1)
	{
		int minn=inf,k=0;
		rep(j,2,n+1)
			if(!vis[j]&&minn>dis[j])
				minn=dis[j],k=j;
		if(!k) break;
		vis[k]=1;
		res+=minn;
		rep(j,2,n+1)
			if(dis[j]>G[k][j])
				dis[j]=G[k][j];
	}
}
inline void solve()
{
	rep(i,1,n+1) rep(j,1,n+1) G[i][j]=read();
	res=0;
	Prim();
	printf("%d",res);
	puts("");
}
int main()
{
	//freopen("C:\\Users\\Administrator\\Desktop\\in.txt","r",stdin);
	while(~scanf("%d",&n)) solve();
	return 0;
}

E - Candies

1.题目描述:
During the kindergarten days, flymouse was the monitor of his class. Occasionally the head-teacher brought the kids of flymouse’s class a large bag of candies and had flymouse distribute them. All the kids loved candies very much and often compared the numbers of candies they got with others. A kid A could had the idea that though it might be the case that another kid B was better than him in some aspect and therefore had a reason for deserving more candies than he did, he should never get a certain number of candies fewer than B did no matter how many candies he actually got, otherwise he would feel dissatisfied and go to the head-teacher to complain about flymouse’s biased distribution.

snoopy shared class with flymouse at that time. flymouse always compared the number of his candies with that of snoopy’s. He wanted to make the difference between the numbers as large as possible while keeping every kid satisfied. Now he had just got another bag of candies from the head-teacher, what was the largest difference he could make out of it?

Input
The input contains a single test cases. The test cases starts with a line with two integers N and M not exceeding 30 000 and 150 000 respectively. N is the number of kids in the class and the kids were numbered 1 through N. snoopy and flymouse were always numbered 1 and N. Then follow M lines each holding three integers A, B and c in order, meaning that kid A believed that kid B should never get over c candies more than he did.

Output
Output one line with only the largest difference desired. The difference is guaranteed to be finite.

Sample Input
2 2
1 2 5
2 1 4
Sample Output
5
Hint
32-bit signed integer type is capable of doing all arithmetic.

2.题意:
大概说的是:班长分糖果,如果A在某种程度上比B优秀,那么他理应得更多的糖果,但是B不觉得A应该比B多太多,得有个程度,否则就会告诉班主任。班长总会最大化同学们的糖果差异数,然后班长和他同桌时常比较糖果数,那么他和同桌的最大差异数是多少。

3.思路:
这是一道差分约束的题目。为啥呢,如果用X代表糖果数,那么Xa-Xb<=c;符合差分系统的定义。我们考虑松弛后的最短路式子:dis[v]<=dis[u]+w,与差分系统的式子相一致,因此我们可以在b到a直接连一条权值为c的有向边。然后跑最短路算法,最后得到的dis数组就是符合条件的X的值。

4.代码:

//E - Candies
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#define FAST ios::sync_with_stdio(false)
#define abs(a) ((a)>=0?a:-a)
#define mem(a,b) memset(a,b,sizeof(a))
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define rep(i,a,n) for(int i=a;i<n;++i)
#define per(i,n,a) for(int i=n-1;i>=a;--i)
using namespace std;
typedef long long ll;
const int maxn = 30000+5;
const int maxm = 150000+5;
const int inf=0x3f3f3f3f;
const double eps = 1e-7;
const int mod = 1e9+7;
inline int lowbit(int x){return x&(-x);}
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
inline ll qpow(ll a,ll b,ll MOD=mod){ll res=1;a%=MOD;while(b>0){if(b&1)res=res*a%MOD;a=a*a%MOD;b>>=1;}return res;}
inline ll inv(ll x,ll p){return qpow(x,p-2,p);}
inline int read()
{
	int x=0,sign=1;
	char c=getchar();
	while(c>'9'||c<'0') {if(c=='-') sign=-1;c=getchar();}
	while('0'<=c&&c<='9') x=x*10+c-'0',c=getchar();
	return x*sign;
}
//head
int n,m;
int head[maxn],cnt;
struct Edge
{
	int v,w,nx;
}edge[maxm];
void add(int u,int v,int w)
{
	edge[++cnt]=(Edge){v,w,head[u]};
	head[u]=cnt;
}
struct node
{
	int u,w;
	bool operator <(const node& a)const
	{
		return w>a.w;
	}
};
int dis[maxn];
bool vis[maxn];
int Dij(int s,int e)
{
	rep(i,1,n+1)
	{
		dis[i]=inf;
		vis[i]=0;
	}
	dis[s]=0;
	priority_queue<node> q;
	q.push((node){s,dis[s]});
	while(!q.empty())
	{
		node tmp=q.top();q.pop();
		int u=tmp.u;
		if(vis[u]) continue;
		vis[u]=1;
		for(int i=head[u];i;i=edge[i].nx)
		{
			int v=edge[i].v;
			int w=edge[i].w;
			if(dis[v]>dis[u]+w)
			{
				dis[v]=dis[u]+w;
				q.push((node){v,dis[v]});
			}
		}
	}
	return dis[e];
}
inline void solve()
{
	mem(head,0);cnt=0;
	while(m--)
	{
		int u=read(),v=read(),w=read();
		add(u,v,w);
	}
	int res=Dij(1,n);
	printf("%d",res);
	puts("");
}
int main()
{
	//freopen("C:\\Users\\Administrator\\Desktop\\in.txt","r",stdin);
	while(~scanf("%d%d",&n,&m)) solve();
	return 0;
}

F - MPI Maelstrom

1.题目描述:
BIT has recently taken delivery of their new supercomputer, a 32 processor Apollo Odyssey distributed shared memory machine with a hierarchical communication subsystem. Valentine McKee’s research advisor, Jack Swigert, has asked her to benchmark the new system.
Since the Apollo is a distributed shared memory machine, memory access and communication times are not uniform,'' Valentine told Swigert.Communication is fast between processors that share the same memory subsystem, but it is slower between processors that are not on the same subsystem. Communication between the Apollo and machines in our lab is slower yet.’’

``How is Apollo’s port of the Message Passing Interface (MPI) working out?’’ Swigert asked.

Not so well,'' Valentine replied.To do a broadcast of a message from one processor to all the other n-1 processors, they just do a sequence of n-1 sends. That really serializes things and kills the performance.’’

``Is there anything you can do to fix that?’’

Yes,'' smiled Valentine.There is. Once the first processor has sent the message to another, those two can then send messages to two other hosts at the same time. Then there will be four hosts that can send, and so on.’’

``Ah, so you can do the broadcast as a binary tree!’’

``Not really a binary tree – there are some particular features of our network that we should exploit. The interface cards we have allow each processor to simultaneously send messages to any number of the other processors connected to it. However, the messages don’t necessarily arrive at the destinations at the same time – there is a communication cost involved. In general, we need to take into account the communication costs for each link in our network topologies and plan accordingly to minimize the total time required to do a broadcast.’’
Input
The input will describe the topology of a network connecting n processors. The first line of the input will be n, the number of processors, such that 1 <= n <= 100.

The rest of the input defines an adjacency matrix, A. The adjacency matrix is square and of size n x n. Each of its entries will be either an integer or the character x. The value of A(i,j) indicates the expense of sending a message directly from node i to node j. A value of x for A(i,j) indicates that a message cannot be sent directly from node i to node j.

Note that for a node to send a message to itself does not require network communication, so A(i,i) = 0 for 1 <= i <= n. Also, you may assume that the network is undirected (messages can go in either direction with equal overhead), so that A(i,j) = A(j,i). Thus only the entries on the (strictly) lower triangular portion of A will be supplied.

The input to your program will be the lower triangular section of A. That is, the second line of input will contain one entry, A(2,1). The next line will contain two entries, A(3,1) and A(3,2), and so on.
Output
Your program should output the minimum communication time required to broadcast a message from the first processor to all the other processors.
Sample Input
5
50
30 5
100 20 50
10 x x 10
Sample Output
35

2.题意:
别看它血长,其实有用的信息就那么几句:它希望消息能从一个点传到另一些点,然后代价尽可能小。

3.思路:
翻译过来其实是:最小生成树问题。为什么呢,从一个点出发生成最小的连通区域。挺明显的最小生成树。给了下三角矩阵,补完用Prim就好啦。

4.代码:

//F - MPI Maelstrom
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#define FAST ios::sync_with_stdio(false)
#define abs(a) ((a)>=0?a:-a)
#define mem(a,b) memset(a,b,sizeof(a))
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define rep(i,a,n) for(int i=a;i<n;++i)
#define per(i,n,a) for(int i=n-1;i>=a;--i)
using namespace std;
typedef long long ll;
const int maxn = 100+5;
const int maxm = 100000+5;
const int inf=0x3f3f3f3f;
const double eps = 1e-7;
const int mod = 1e9+7;
inline int lowbit(int x){return x&(-x);}
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
inline ll qpow(ll a,ll b,ll MOD=mod){ll res=1;a%=MOD;while(b>0){if(b&1)res=res*a%MOD;a=a*a%MOD;b>>=1;}return res;}
inline ll inv(ll x,ll p){return qpow(x,p-2,p);}
inline int read()
{
	int x=0,sign=1;
	char c=getchar();
	while(c>'9'||c<'0'){if(c=='-') sign=-1;else if(c=='x') return inf;c=getchar();}
	while('0'<=c&&c<='9') x=x*10+c-'0',c=getchar();
	return x*sign;
}
//head
int n,m;
int G[maxn][maxn];
int dis[maxn];
bool vis[maxn];
inline int Prim(int s)
{
	rep(i,1,n+1)
	{
		dis[i]=G[s][i];
		vis[i]=0;
	}
	dis[s]=vis[s]=0;
	int res=0;
	rep(i,1,n+1)
	{
		int minn=inf,k=0;
		rep(j,1,n+1) if(!vis[j]&&minn>dis[j]) minn=dis[j],k=j;
		vis[k]=true;
		rep(j,1,n+1) if(dis[j]>dis[k]+G[k][j]) dis[j]=dis[k]+G[k][j];
	}
	rep(i,1,n+1) res=max(res,dis[i]);
	return res;
}
inline void solve()
{
	mem(G,0);
	rep(i,1,n+1)
		rep(j,1,i)
			G[i][j]=G[j][i]=read();
	int ans=Prim(1);
	printf("%d",ans);
	puts("");
}
int main()
{
	//freopen("C:\\Users\\Administrator\\Desktop\\in.txt","r",stdin);
	while(~scanf("%d",&n)) solve();
	return 0;
}

H - Borg Maze

1.题意:
The Borg is an immensely powerful race of enhanced humanoids from the delta quadrant of the galaxy. The Borg collective is the term used to describe the group consciousness of the Borg civilization. Each Borg individual is linked to the collective by a sophisticated subspace network that insures each member is given constant supervision and guidance.

Your task is to help the Borg (yes, really) by developing a program which helps the Borg to estimate the minimal cost of scanning a maze for the assimilation of aliens hiding in the maze, by moving in north, west, east, and south steps. The tricky thing is that the beginning of the search is conducted by a large group of over 100 individuals. Whenever an alien is assimilated, or at the beginning of the search, the group may split in two or more groups (but their consciousness is still collective.). The cost of searching a maze is definied as the total distance covered by all the groups involved in the search together. That is, if the original group walks five steps, then splits into two groups each walking three steps, the total distance is 11=5+3+3.
Input
On the first line of input there is one integer, N <= 50, giving the number of test cases in the input. Each test case starts with a line containg two integers x, y such that 1 <= x,y <= 50. After this, y lines follow, each which x characters. For each character, a space '' stands for an open space, a hash mark#’’ stands for an obstructing wall, the capital letter A'' stand for an alien, and the capital letterS’’ stands for the start of the search. The perimeter of the maze is always closed, i.e., there is no way to get out from the coordinate of the ``S’’. At most 100 aliens are present in the maze, and everyone is reachable.
Output
For every test case, output one line containing the minimal cost of a succesful search of the maze leaving no aliens alive.
Sample Input

在这里插入图片描述

Sample Output
8
11

2.题意:
由于这个排版的问题,其实某些空格我用_代替,但是还是弄不好,干脆直接截图了,记住某些地方是有“ ”(空格)的。题目说的是,有一群人,在开始时或者抓到外星人时可以分裂成多个团体帮忙寻找外星人。他们行进的路程是群体的总行进路程之和,问最小行进的步数。

3.思路:
当时做完全不敢暴力,想着想不出来,上网一搜,还真就贼暴力。bfs+Prim。把A和S当成节点,每个节点用bfs跑出到其他节点的最小距离,然后连成最小生成树。

4.代码:

//H - Borg Maze
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
#define FAST ios::sync_with_stdio(false)
#define abs(a) ((a)>=0?(a):-(a))
#define sz(x) ((int)(x).size())
#define all(x) (x).begin(),(x).end()
#define mem(a,b) memset(a,b,sizeof(a))
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define rep(i,a,n) for(int i=a;i<n;++i)
#define per(i,n,a) for(int i=n-1;i>=a;--i)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef pair<int,int> PII;
typedef long long ll;
const int maxn = 1000+5;
const int maxm = 1000+5;
const int inf=0x3f3f3f3f;
const double eps = 1e-7;
const int mod = 1e9+7;
inline int lowbit(int x){return x&(-x);}
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
inline ll qpow(ll a,ll b,ll MOD=mod){ll res=1;a%=MOD;while(b>0){if(b&1)res=res*a%MOD;a=a*a%MOD;b>>=1;}return res;}
inline ll inv(ll x,ll p){return qpow(x,p-2,p);}
inline int read()
{
	int x=0,sign=1;
	char c=getchar();
	while(c>'9'||c<'0') {if(c=='-') sign=-1;c=getchar();}
	while('0'<=c&&c<='9') x=x*10+c-'0',c=getchar();
	return x*sign;
}
//head
int n,m;
string g[maxn];
vector<PII> v;
int G[maxn][maxn];
bool vis[maxn][maxn];
int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
bool check(int x,int y)
{
	return !((0<=x&&x<n)&&(0<=y&&y<m));
}
struct node
{
	PII pos;
	int step;
};
inline void bfs(int s)
{
	mem(vis,0);
	queue<node> q;
	q.push((node){v[s],0});
	vis[v[s].fi][v[s].se]=1;
	while(!q.empty())
	{
		node tmp=q.front();q.pop();
		rep(i,0,sz(v))
			if(tmp.pos==v[i])
			{
				G[s][i]=tmp.step;
				break;
			}
		rep(i,0,4)
		{
			int x=tmp.pos.fi+dir[i][0];
			int y=tmp.pos.se+dir[i][1];
			if(vis[x][y]||check(x,y)||g[x][y]=='#') continue;
			vis[x][y]=1;
			q.push((node){mp(x,y),tmp.step+1}); 
		}
	}
}
int dis[maxn];
bool Vis[maxn];
inline int Prim()
{
	int res=0,k=-1;
	rep(i,0,sz(v)) dis[i]=G[0][i],Vis[i]=0;
	Vis[0]=1;
	rep(i,1,sz(v))
	{
		int minn=inf;
		rep(j,0,sz(v)) if(!Vis[j]&&minn>dis[j]) minn=dis[j],k=j;
		Vis[k]=1;res+=minn;
		rep(j,0,sz(v)) if(dis[j]>G[k][j]) dis[j]=G[k][j];
	}
	return res;
}
inline void solve()
{
	m=read(),n=read();
	rep(i,0,n) getline(cin,g[i]);
	rep(i,0,n) rep(j,0,m) if(g[i][j]=='A'||g[i][j]=='S') v.pb(mp(i,j));
	rep(i,0,sz(v)) bfs(i);
	int res=Prim();
	printf("%d",res);
	puts("");
	v.clear();
}
int main()
{
	//freopen("C:\\Users\\Administrator\\Desktop\\in.txt","r",stdin);
	for(int Case=read();Case;Case--) solve();
	return 0;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值