2019-假期第三场(2019.2.1)

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.

  1. All cities must still be served.
  2. There will be no multiple services/route to the same city.
  3. 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. 1 ≤ n ≤ 10, 000, where n is the number of lines.
  2. 1 ≤ m ≤ 100, 000, where m is the number of links.
  3. 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);
        }

    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值