7001 Bus Problem
ACM Bus company runs a large bus network. To go from city A to city B, there could be a express
route with no stops between the two cities. There could also be local routes with stops at different
cities prior to city B. However, ever since the ICPC high speed rail went into operation, ACM Bus
company has been steadily losing customers. It is no longer financially possible to maintain so many
bus routes. The annual cost of maintaining 1 kilometer of bus route is $1. The ACM board has decided
to streamline all the routes serviced by the company in order to lower the total maintenance cost. In
consequence, many of the routes (whether be direct or indirect routes) are to be eliminated. The ACM
board proposed three simple rules in eliminating the routes.
- All cities must still be served.
- There will be no multiple services/route to the same city.
- The total routes eliminated in terms of kilometres must be as large as possible.
Given the bus route map, forecast the annual total saving in maintenance cost if the board’s plan is
put into practice.
Technical Specification
• The number of cities served is c, 2 ≤ c ≤ 1, 000. The cities are numbered from 0 to c − 1.
• The number of express routes is r, 1 ≤ r ≤ c(c − 1)/2. The distance of any express route is
between 1 and 1000 kilometers.
Input
First line of input is an integer n, n ≤ 15, indicating number of test cases to follow. For each test case,
the first line contains two integers c and r, indicating the number of cities and the number of express
routes, respectively. The next r lines each contains three integers c1 , c2, and dist, indicating that there
is an express route between cities c1 and c2 and the distance between the two cities is dist kilometers.
Output
For each test case, output the projected saving if the ACM Board’s plan is put into practice.
Sample Input
2
3 3
0 1 3
2 1 1
2 0 2
4 5
3 2 4
1 0 4
2 1 1
0 2 2
1 3 2
Sample Output
3
8
题意:
给定 n 个城市,m 条道路,给定 a,b两条城市之间的距离 c
两个城市之间有多条道路可达,现在保证:
(1).每个城市之间都有道路可达
(2).到达同一城市没有多条道路
(3).到同一城市如果有多条道路,去除该条道路,使得去掉道路的总和最大
求去掉道路总和的最大值?
本以为是最短路的模板题,用迪杰斯特拉模板来做,后来第一组样例wrong,可能是因为迪杰斯特拉没法判断负环的问题
其实是最小生成树类型
思路:
n个城市只需要 n - 1 条道路就可以连接,然后对 m 条权值排序
留下最小的 n -1 条道路就可以,把剩余的去掉
CODE:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <set>
#include <map>
typedef long long LL;
using namespace std;
#define memset(a,n) memset(a,n,sizeof(a))
#define INF 0x3f3f3f3f
bool cmp(int a,int b)
{
return a>b;
}
int main()
{
int dis[1005];
int t,n,m,be,en,sum,nn;
scanf("%d",&t);
while(t--){
memset(dis,0);
scanf("%d %d",&n,&m);
sum=0;
for(int i=0;i<m;i++)
scanf("%d %d %d",&be,&en,&dis[i]);
sort(dis,dis+m,cmp);
int nn=m-n+1;
for(int i=0;i<nn;i++){
//cout<<dis[i]<<"**"<<endl;
sum+=dis[i];
}
printf("%d\n",sum);
}
}
最小生成树模板:
2、
7000 Present Problem
A group of persons (indexed from 0 to n − 1) play a game to determine which of the n presents (also
indexed from 0 to n − 1) each of them will get. They play the game on a system of n vertical “lines”,
numbered from 0 to n − 1, from left to right. Person i initially is at the top of line i, and present i
is at the bottom of line i. All lines have length l. There are also horizontal “links” that connect two
adjacent lines i and i + 1 at the same length k, where k is an integer distance from the top end of the
line, and 0 < k < l. We use link (i, k) to denote this link. In addition, two links adjacent to a line
cannot be at the same length of the line. That is, we cannot have both links (i, k) and (i + 1, k).
Person i determines which present he will receive as follows. He will start from the top of line i and
go downward. Whenever he encounters an intersection of a line and a link, he has to make a turn, and
he can go either left or right along a link, or downward along a line. Finally he will reach the bottom
of a line j, and he will receive present j.
We use Figure 1 to illiterate the rules. Person 1 starts from the top of line 1 and goes downward.
He first reaches the link at (1, 1) and makes a turn to line 2, and keeps going downward. Then he
reaches the link at (2, 3) and makes another turn to line 3. He keeps on going, as indicated by the path
in Figure 1, and finally reaches present 4.
Your task is to determine for all persons, what presents do they receive, and list the present indices
from person 0 to person n − 1. In the previous example you should output 3, 4, 1, 0, 5, 2, because
person 0 will get present 3, person 1 will get present 4, and so on.
Technical Specification
- 1 ≤ n ≤ 10, 000, where n is the number of lines.
- 1 ≤ m ≤ 100, 000, where m is the number of links.
- 1 ≤ l ≤ 10, 000, where l is the length of the lines.
Input
The first line of the input has the number of test cases c. For each test case, the first line has n, m, and
l, indicating the number of lines, the number of links, and the length of the lines respectively. Each of
the next m lines contains two integers i and k, to indicate a link at (i, k).
Output
For each test case, your should output n lines, where the i-line is the present id person i will receive.
Sample Input
1
6 10 8
0 2
2 6
0 7
1 1
4 2
4 5
1 4
2 3
3 4
4 7
Sample Output
3
4
1
0
5
2
题意:
给定 n 个人,n个礼物,人站在线的上方,礼物在线的下方(类似于迷宫,入口在上方出口在下方)
m 条线有相同的长度 L(代表迷宫的从上方到下方的长为 L)
长度和人数 类似于二维数组
给定 (i,k),与( i+1,k ) 连接一条水平线
//( i 代表第几个人, k 代表长度也就是竖着的那一列,类似于二维数组的 i )
例上图所示:
(0,2): 将 (0,2)和(1,2)连接一条线
(也就是二维数组的 (2,0)、(2,1)连接一条线
用二维数组的话需要注意一下这里)
思路:
当同一个 k 时,将有线连接的两个人之间用特殊值标记
首先想的是用 1 来标记,但没考虑全面
例如:
0 1 2 3
1 _______ _______
vis[1][0]=1,vis[1][1]=1,vis[1][2]=1,vis[1][3]=1
那么去判断条件时,得到的 1 2 之间也是有线的(因为有同样的标记值)
所以改进方法是:
这个特殊的标记值给定 两个相邻人的和
即 vis[1][0]=1,vis[1][1]=1,vis[1][2]=3,vis[1][3]=3
CODE:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <set>
#include <map>
typedef long long LL;
using namespace std;
#define memset(a,n) memset(a,n,sizeof(a))
#define INF 0x3f3f3f3f
int vis[10002][10002];
int mapp[10002];
int main()
{
int t,n,m,l;
scanf("%d",&t);
while(t--){
memset(vis,0);
memset(mapp,0);
scanf("%d %d %d",&n,&m,&l);
//cout<<n<<"*"<<m<<endl;
int x,k;
for(int i=0;i<m;i++){
scanf("%d %d",&x,&k);
vis[k][x]=x+x+1;
vis[k][x+1]=x+x+1;
}
int ans;
for(int i=0;i<n;i++){
ans=i;
for(int j=1;j<=l;j++){
// cout<<ans<<"**"<<endl;
if(ans==0){
if((vis[j][ans]==vis[j][ans+1])&&vis[j][ans]!=0)
ans++;
}
else if(ans==n-1){
if((vis[j][ans]==vis[j][ans-1])&&vis[j][ans]!=0)
ans--;
}
else{
if((vis[j][ans]==vis[j][ans+1])&&vis[j][ans]!=0){
ans++;
continue;
// 这里栽了一下,若不加 continue,则进行完 ans++ 之后,满足了下一个条件
}
if((vis[j][ans]==vis[j][ans-1])&&vis[j][ans]!=0)
ans--;
}
}
printf("%d\n",ans);
}
}
}