多源最短路训练题解(floyd模板+ 无向图+ 有向图+10多道类型题解)

还有16天就要比省赛了,复习一波最短路首先是floyd的应用

需要注明的一点第一个K是松弛了k个城市

 

练习题解:   

 HDU1596
   HDU2112  
   HDU1874  
   HDU1869

 HDU2066  
   HDU2094
   HDU2544
稍加复杂:
HDU1217    顺练习map离散    难度1.5
HDU1245    处理起点,终点    难度2.5
HDU1535    2次迪杰斯特拉       难度2
HDU2170                      难度x
HDU3631                      难度x
HDU4284   BFS+floyd        难度2.5
加深对k的理解: 
 HDU1599(最小环)

 

 

暴富的小灰

时间限制: 1 Sec  内存限制: 128 MB
提交: 30  解决: 12
[提交] [状态] [讨论版] [命题人:外部导入]

 

题目描述

小灰怎么可能暴富呢!!!最近上映了一部电影,叫做“西虹市首富”,小灰看完电影做了个梦,梦到自己被要求在一个月内花光十个亿的鼠币,它决定带着小白去旅行,从X城一路旅行到Y城,小灰想知道怎么走才能花最多的钱,你能帮助小灰吗?

输入

第一行三个正整数N,X,Y,分别表示城市的个数,旅行的起点,旅行的终点;第二行N个正整数K,表示每个城市旅行的花费;接下来的N-1行,每行有两个正整数U,V,表示能从U城市到达V城市。

输出

输出小灰最多能花费多少钱,如果从X城市不能到达Y城市,则输出-1

样例输入

6 1 6
7 3 4 2 8 5
1 2
2 3
3 6
4 2
5 2

样例输出

19

提示

1 <= N <= 150
1 <= K <= 10000

 

floyd裸题,花费弄成负的转化成最短路

# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
#include 

using namespace std;
#define ll long long int
const int inf = 0x3f3f3f3f;
const int maxn = 2e2 + 1;
int book[maxn][maxn];
int dis[maxn];
void fun()
{
    memset(dis, false, sizeof(dis));
    for(int i = 0; i < maxn; i++)
    {
        for(int j = 0; j < maxn; j++)
        {
            if(i == j)
                book[i][j] = 0;
            else
                book[i][j] = inf;
        }
    }
}
int main(int argc, char  *argv[])
{
    int n, sx, ex;
    while(cin >> n >> sx >> ex)
    {
        fun();
        for(int i = 1; i <= n; i++)
        {
            cin >> dis[i];
            dis[i] = -dis[i];
        //    cout << dis[i] << endl;
        }
        for(int i = 0; i < n- 1; i++)
        {
            int u, v;
             cin >> u >> v;
             book[u][v] = dis[u];
        }
        for(int k = 1; k <= n; k++)
        {
            for(int i = 1; i <= n; i++)
            {
                for(int j = 1; j <= n; j++)
                {
                    if(book[i][k] < inf && book[k][j] < inf && book[i][j] > book[i][k] + book[k][j])
                    {
                        book[i][j] = book[i][k] + book[k][j];
                    }
                }
            }
        }
        if(book[sx][ex] >= inf)
        {
            cout << -1 << endl;
        }
        else
            cout << -(book[sx][ex] + dis[ex]) << endl;

    }


	return 0;
}

 

Travel Cost

时间限制: 1 Sec  内存限制: 128 MB
提交: 38  解决: 21
[提交] [状态] [讨论版] [命题人:*Administrator]

 

题目描述

AC country is a famous and beautiful place. There are N cities in the country, numbered as 1,2,3...N。The first city is the capital of AC, so it is the greatest and best place all over the country. Many travelers often get a travel in AC.  ACMer and his girl friends like the fine view and beautiful scenery in AC, so they plan to get a travel in AC recently. AC and his N-1 girl friends go to the AC by plane  land at the capital airport. They wants to get a travel to every city of AC but independently. in other words, the first girl friend goes to the first city, the second girl friend goes to the second city,the rest can be done in the same manner.
In AC country, there maybe at most one road between every two different cities. One girl will spend some money if  she passes one road correspondingly. ACMer must offer all the travel cost of all his girl friends. He wants to known what is the minimum total cost if evry girl gets her travel by the most economic strategy ?

输入

There are many test case waiting for your program code!
In every case, the first line of the input will be N (1<=N<=100), the number of cites.
The rest of the input defines an N*N adjacency matrix. Each of its entries will be either an integer or the character x. The value of MAT(i,j) indicates the expense of sending a travel  directly from city i to city j. A value of x for MAT(i,j) indicates that there is no directly road from city to city j. 

Note that for a city to itself does not require any cost, so MAT(i,i) = 0 for all integer i in range(1,N). Also, you may assume that the road is undirected, so that MAT(i,j) = MAT(j,i). Thus the imput data only supply the entries on the lower triangular portion of adjacency matrix strictly. 

The input of your program will be the lower triangular section of matrix . That is, the second line of input will contain only, MAT(2,1). The next line will contain two entries, MAT(3,1) and MAT(3,2), and so on. All MAT(i,j) will not greater than 1000.

输出

for every case, output the minimum total cost of all ACMer's all girl friends,  one per line.

样例输入

5
40
30 6
99 24 36
25 x x 25

样例输出

141

裸的最短路

# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
#include 

using namespace std;
#define ll long long int
const int inf = 0x3f3f3f3f;
const int maxn = 1e2 + 10;
int book[maxn][maxn];
void fun()
{
    for(int i = 0; i < maxn; i++)
    {
        for(int j = 0; j < maxn; j++)
        {
            if(i == j)
                book[i][j] = 0;
            else
                book[i][j] = inf;
        }
    }
}
int main(int argc, char  *argv[])
{
    int n;
    while(cin >> n)
    {
        fun();
        for(int i = 2; i <= n; i++)
        {
            for(int j = 1; j < i; j++)
            {
                string str;
                cin >> str;
                if(str != "x")
                {
                    int flag = 0;
                    for(int k = 0; k < str.size(); k++)
                    {
                        flag *= 10;
                        flag += str[k] - '0';
                    }
                //    cout << flag << endl;
                    book[i][j] = flag;
                    book[j][i] = flag;
                }
                }

            }
            for(int k = 1; k <= n; k++)
        {
            for(int i = 1; i <= n; i++)
            {
                for(int j = 1; j <= n; j++)
                {
                    if(book[i][k] < inf && book[k][j] < inf && book[i][j] > book[i][k] + book[k][j])
                    {
                        book[i][j] = book[i][k] + book[k][j];
                    }
                }
            }
        }
        int sum = 0;
        for(int i = 1; i<= n; i++)
            sum += book[1][i];
        cout << sum << endl;

        }


	return 0;
}

find the safest road

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 18643    Accepted Submission(s): 6364


 

Problem Description

XX星球有很多城市,每个城市之间有一条或多条飞行通道,但是并不是所有的路都是很安全的,每一条路有一个安全系数s,s是在 0 和 1 间的实数(包括0,1),一条从u 到 v 的通道P 的安全度为Safe(P) = s(e1)*s(e2)…*s(ek) e1,e2,ek是P 上的边 ,现在8600 想出去旅游,面对这这么多的路,他想找一条最安全的路。但是8600 的数学不好,想请你帮忙 ^_^

 

 

Input

输入包括多个测试实例,每个实例包括:
第一行:n。n表示城市的个数n<=1000;
接着是一个n*n的矩阵表示两个城市之间的安全系数,(0可以理解为那两个城市之间没有直接的通道)
接着是Q个8600要旅游的路线,每行有两个数字,表示8600所在的城市和要去的城市

 

 

Output

如果86无法达到他的目的地,输出"What a pity!",
其他的输出这两个城市之间的最安全道路的安全系数,保留三位小数。

 

 

Sample Input

 

3 1 0.5 0.5 0.5 1 0.4 0.5 0.4 1 3 1 2 2 3 1 3

 

 

Sample Output

 

0.500 0.400 0.500

 

# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
#include
# include 
#include 

using namespace std;
#define ll long long int
const int inf = 0x3f3f3f3f;
const int maxn = 1e3 + 1;
double book[maxn][maxn];
int dis[maxn];
void fun()
{
    memset(dis, false, sizeof(dis));
    for(int i = 0; i < maxn; i++)
    {
        for(int j = 0; j < maxn; j++)
        {
            if(i == j)
                book[i][j] = 0;
            else
                book[i][j] = inf;
        }
    }
}
int main(int argc, char  *argv[])
{
   // ios_base::sync_with_stdio(false);
    int n, sx, ex;
    while(scanf("%d",&n) !=EOF)
    {
        memset(book, false, sizeof(book));
        for(int i = 1; i <= n; i++)
        {
            for(int j = 1; j <= n; j++)
            {
                scanf("%lf",&book[i][j]);
            }
        }
        for(int k = 1; k <= n; k++)
        {
            for(int i = 1; i <= n; i++)
            {
                for(int j = 1; j <= n; j++)
                {
                    if(book[i][k] > 0 && book[k][j] > 0 && book[i][j] < book[i][k] * book[k][j])
                    {
                        book[i][j] = book[i][k] * book[k][j];
                    }
                }
            }
        }
        int q;
        scanf("%d",&q);
        for(int i = 0; i < q; i++)
        {
            int u, v;
           scanf("%d%d",&u,&v);
            if(book[u][v] > 0)
            {
             printf("%.3lf\n", book[u][v]);
            }
            else
            {
                printf("What a pity!\n");
            }
        }



    }


	return 0;
}

 

HDU Today

Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 41977    Accepted Submission(s): 10024


 

Problem Description

经过锦囊相助,海东集团终于度过了危机,从此,HDU的发展就一直顺风顺水,到了2050年,集团已经相当规模了,据说进入了钱江肉丝经济开发区500强。这时候,XHD夫妇也退居了二线,并在风景秀美的诸暨市浬浦镇陶姚村买了个房子,开始安度晚年了。
这样住了一段时间,徐总对当地的交通还是不太了解。有时很郁闷,想去一个地方又不知道应该乘什么公交车,在什么地方转车,在什么地方下车(其实徐总自己有车,却一定要与民同乐,这就是徐总的性格)。
徐总经常会问蹩脚的英文问路:“Can you help me?”。看着他那迷茫而又无助的眼神,热心的你能帮帮他吗?
请帮助他用最短的时间到达目的地(假设每一路公交车都只在起点站和终点站停,而且随时都会开)。

 

 

Input

输入数据有多组,每组的第一行是公交车的总数N(0<=N<=10000);
第二行有徐总的所在地start,他的目的地end;
接着有n行,每行有站名s,站名e,以及从s到e的时间整数t(0 note:一组数据中地名数不会超过150个。
如果N==-1,表示输入结束。

 

 

Output

如果徐总能到达目的地,输出最短的时间;否则,输出“-1”。

 

 

Sample Input

 

6 xiasha westlake xiasha station 60 xiasha ShoppingCenterofHangZhou 30 station westlake 20 ShoppingCenterofHangZhou supermarket 10 xiasha supermarket 50 supermarket westlake 10 -1

 

 

Sample Output

 

50 Hint: The best route is: xiasha->ShoppingCenterofHangZhou->supermarket->westlake 虽然偶尔会迷路,但是因为有了你的帮助 **和**从此还是过上了幸福的生活。 ――全剧终――

 

 

Author

lgx

用map离散化一下

# if 01
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
#include
# include 
#include 

using namespace std;
#define ll long long int
const int inf = 0x3f3f3f3f;
const int maxn = 1e2 + 5;
int book[maxn][maxn];
int dis[maxn];
void fun()
{
    memset(dis, false, sizeof(dis));
    for(int i = 0; i < maxn; i++)
    {
        for(int j = 0; j < maxn; j++)
        {
            if(i == j)
                book[i][j] = 0;
            else
                book[i][j] = inf;
        }
    }
}
int main(int argc, char  *argv[])
{
    int n;
    while(scanf("%d", &n) != EOF&& n != -1)
    {
        char Start[40], End[40], str1[40], str2[40];
        map m;
        fun();
        int c = 1;
        scanf("%s%s",Start, End);
        m[Start] = 1;
        if(m[End] == 0)
        {
            m[End] = ++ c;
        }
        for(int i = 1; i <= n; i++)
        {
            int len;
            scanf("%s%s%d", str1, str2, &len);
            if(m[str1] == 0)
            {
                m[str1] = ++c;
            }
            if(m[str2] == 0)
            {
                m[str2] = ++c;
            }
            if(book[m[str1]][m[str2]] > len)
            {
                book[m[str1]][m[str2]] =book[m[str2]][m[str1]]  = len;
            }
        }

        if(strcmp(Start,End) == 0)
        {
            printf("0\n");
            continue;
        }
        for(int k = 1; k <= c; k++)
        {
            for(int i = 1; i <= c; i++)
            {
                for(int j = 1; j <= c+ 1; j++)
                {
                    if(book[i][k] < inf&& book[k][j] < inf && book[i][j] > book[i][k] + book[k][j])
                    {
                        book[i][j] = book[i][k] + book[k][j];
                    }
                }
            }
        }
    int ans = book[m[Start]][m[End]];
       if(book[m[Start]][m[End]] < inf)
       {
           printf("%d\n",ans);
       }
       else
            printf("-1\n");

    }
	return 0;
}
#endif // 0

 

 

畅通工程续

Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 78535    Accepted Submission(s): 30236


 

Problem Description

某省自从实行了很多年的畅通工程计划后,终于修建了很多路。不过路多了也不好,每次要从一个城镇到另一个城镇时,都有许多种道路方案可以选择,而某些方案要比另一些方案行走的距离要短很多。这让行人很困扰。

现在,已知起点和终点,请你计算出要从起点到终点,最短需要行走多少距离。

 

 

Input

本题目包含多组数据,请处理到文件结束。
每组数据第一行包含两个正整数N和M(0 接下来是M行道路信息。每一行有三个整数A,B,X(0<=A,B 再接下一行有两个整数S,T(0<=S,T

 

 

Output

对于每组数据,请在一行里输出最短需要行走的距离。如果不存在从S到T的路线,就输出-1.

 

 

Sample Input

 

3 3 0 1 1 0 2 3 1 2 1 0 2 3 1 0 1 1 1 2

 

 

Sample Output

 

2 -1

 

 

Author

linle

 

 

Source

2008浙大研究生复试热身赛(2)——全真模拟

 

 

 

 

 

# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
#include
# include 
#include 

using namespace std;
#define ll long long int
const int inf = 0x3f3f3f3f;
const int maxn = 2e2 + 5;
int book[maxn][maxn];
int dis[maxn];
void fun()
{
    memset(dis, false, sizeof(dis));
    for(int i = 0; i < maxn; i++)
    {
        for(int j = 0; j < maxn; j++)
        {
            if(i == j)
                book[i][j] = 0;
            else
                book[i][j] = inf;
        }
    }
}
int main(int argc, char  *argv[])
{
   // ios_base::sync_with_stdio(false);
    int n, m;
    while(scanf("%d%d",&n,&m) !=EOF)
    {
        fun();
        for(int i = 1; i <= m; i++)
        {
            int x, y, len;
            scanf("%d%d",&x,&y);
            scanf("%d",&len);
            if(len < book[x][y])//注意特盘最短的路
                book[y][x] = book[x][y] = len;
        }
        int ex, ey;
        scanf("%d%d",&ex, &ey);
        for(int k = 0; k < n; k++)
        {
            for(int i = 0; i < n; i++)
            {
                for(int j = 0; j < n; j++)
                {
                    if(book[i][k] < inf&& book[k][j] < inf && book[i][j] > book[i][k] + book[k][j])
                    {
                        book[i][j] = book[i][k] + book[k][j];
                    }
                }
            }
        }
        if(book[ex][ey] == inf)
        {
            printf("-1\n");
        }
        else
        {
            printf("%d\n",book[ex][ey]);
        }

    }
	return 0;
}

 

六度分离

Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 13756    Accepted Submission(s): 5537


 

Problem Description

1967年,美国著名的社会学家斯坦利·米尔格兰姆提出了一个名为“小世界现象(small world phenomenon)”的著名假说,大意是说,任何2个素不相识的人中间最多只隔着6个人,即只用6个人就可以将他们联系在一起,因此他的理论也被称为“六度分离”理论(six degrees of separation)。虽然米尔格兰姆的理论屡屡应验,一直也有很多社会学家对其兴趣浓厚,但是在30多年的时间里,它从来就没有得到过严谨的证明,只是一种带有传奇色彩的假说而已。

Lele对这个理论相当有兴趣,于是,他在HDU里对N个人展开了调查。他已经得到了他们之间的相识关系,现在就请你帮他验证一下“六度分离”是否成立吧。

 

 

Input

本题目包含多组测试,请处理到文件结束。
对于每组测试,第一行包含两个整数N,M(0 接下来有M行,每行两个整数A,B(0<=A,B 除了这M组关系,其他任意两人之间均不相识。

 

 

Output

对于每组测试,如果数据符合“六度分离”理论就在一行里输出"Yes",否则输出"No"。

 

 

Sample Input

 

8 7 0 1 1 2 2 3 3 4 4 5 5 6 6 7 8 8 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 0

 

 

Sample Output

 

Yes Yes

 

 

Author

linle

 

# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
#include
# include 
#include 

using namespace std;
#define ll long long int
const int inf = 0x3f3f3f3f;
const int maxn = 2e2 + 5;
int book[maxn][maxn];
int dis[maxn];
void fun()
{
    memset(dis, false, sizeof(dis));
    for(int i = 0; i < maxn; i++)
    {
        for(int j = 0; j < maxn; j++)
        {
            if(i == j)
                book[i][j] = 0;
            else
                book[i][j] = inf;
        }
    }
}

bool check(int n)
{
    for(int i = 0; i < n; i++)
    {
        for(int j = 0; j < n; j++)
        {
            if( book[i][j] > 7)
                return 0;
        }
    }
    return true;
}
int main(int argc, char  *argv[])
{
    int n, m;
    while(scanf("%d%d",&n,&m) !=EOF)
    {
        fun();
        for(int i = 1; i <= m; i++)
        {
            int x, y, len;
            scanf("%d%d",&x,&y);
                book[y][x] = book[x][y] = 1;
        }
        for(int k = 0; k < n; k++)
        {
            for(int i = 0; i < n; i++)
            {
                for(int j = 0; j < n; j++)
                {
                    if(book[i][k] < inf&& book[k][j] < inf && book[i][j] > book[i][k] + book[k][j])
                    {
                        book[i][j] = book[i][k] + book[k][j];
                        book[j][i] = book[i][j];
                    }
                }
            }
        }
        if(!check(n))
        {
            printf("No\n");
        }
        else
        {
            printf("Yes\n");
        }
    }
	return 0;
}

一个人的旅行

Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 56733    Accepted Submission(s): 18853


 

Problem Description

虽然草儿是个路痴(就是在杭电待了一年多,居然还会在校园里迷路的人,汗~),但是草儿仍然很喜欢旅行,因为在旅途中 会遇见很多人(白马王子,^0^),很多事,还能丰富自己的阅历,还可以看美丽的风景……草儿想去很多地方,她想要去东京铁塔看夜景,去威尼斯看电影,去阳明山上看海芋,去纽约纯粹看雪景,去巴黎喝咖啡写信,去北京探望孟姜女……眼看寒假就快到了,这么一大段时间,可不能浪费啊,一定要给自己好好的放个假,可是也不能荒废了训练啊,所以草儿决定在要在最短的时间去一个自己想去的地方!因为草儿的家在一个小镇上,没有火车经过,所以她只能去邻近的城市坐火车(好可怜啊~)。

 

 

Input

输入数据有多组,每组的第一行是三个整数T,S和D,表示有T条路,和草儿家相邻的城市的有S个,草儿想去的地方有D个;
接着有T行,每行有三个整数a,b,time,表示a,b城市之间的车程是time小时;(1=<(a,b)<=1000;a,b 之间可能有多条路)
接着的第T+1行有S个数,表示和草儿家相连的城市;
接着的第T+2行有D个数,表示草儿想去地方。

 

 

Output

输出草儿能去某个喜欢的城市的最短时间。

 

 

Sample Input

 

6 2 3 1 3 5 1 4 7 2 8 12 3 8 4 4 9 12 9 10 2 1 2 8 9 10

 

 

Sample Output

 

9

 

 

Author

Grass

 

 

Source

RPG专场练习赛

 

记录下想去的地方和自己家,然后找最短距离就可以

//hdu 2066
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
#include
# include 
#include 

using namespace std;
#define ll long long int
const int inf = 0x3f3f3f3f;
const int maxn = 1e3 + 5;
int book[maxn][maxn];
int dis[maxn];
void fun()
{
    memset(dis, false, sizeof(dis));
    for(int i = 0; i < maxn; i++)
    {
        for(int j = 0; j < maxn; j++)
        {
            if(i == j)
                book[i][j] = 0;
            else
                book[i][j] = inf;
        }
    }
}

int main(int argc, char  *argv[])
{
   // ios_base::sync_with_stdio(false);
    int t, n, m;
    while(scanf("%d%d%d",&t,&n,&m) !=EOF)
    {
        fun();
        int q = 0;
        int mm = inf;
        for(int i = 1; i <= t; i++)
        {
            int x, y, len;
            scanf("%d%d",&x,&y);
            scanf("%d",&len);
            q = max(max(x, y), q);
            mm = min(min(x, y), mm);
            if(len < book[x][y])
                book[y][x] = book[x][y] = len;
        }
        int arr[maxn], brr[maxn];
        for(int i = 1; i <= n; i++)
        {
            scanf("%d",&arr[i]);
        }
        for(int i = 1; i <= m; i++)
        {
             scanf("%d",&brr[i]);
        }
        for(int k = mm; k <= q; k++)
        {
            for(int i = mm; i <= q; i++)
            {
                if(book[i][k] != inf)
                {
                    for(int j = mm; j <= q; j++)
                    {
                        if(book[i][j] > book[i][k] + book[k][j])
                        {
                            book[i][j] = book[i][k] + book[k][j];
                            book[j][i] = book[i][j];
                        }
                    }
                }
            }
        }
        int ans = inf;
        for(int i = 1; i<= n; i++)
        {
            for(int j = 1; j <= m; j++)
            {
                if(ans > book[arr[i]][brr[j]])
                {
                    ans = book[arr[i]][brr[j]];
                }
            }
        }
        printf("%d\n", ans);

    }
    return 0;
}

 

产生冠军

Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 24987    Accepted Submission(s): 11174


 

Problem Description

有一群人,打乒乓球比赛,两两捉对撕杀,每两个人之间最多打一场比赛。
球赛的规则如下:
如果A打败了B,B又打败了C,而A与C之间没有进行过比赛,那么就认定,A一定能打败C。
如果A打败了B,B又打败了C,而且,C又打败了A,那么A、B、C三者都不可能成为冠军。
根据这个规则,无需循环较量,或许就能确定冠军。你的任务就是面对一群比赛选手,在经过了若干场撕杀之后,确定是否已经实际上产生了冠军。

 

 

Input

输入含有一些选手群,每群选手都以一个整数n(n<1000)开头,后跟n对选手的比赛结果,比赛结果以一对选手名字(中间隔一空格)表示,前者战胜后者。如果n为0,则表示输入结束。

 

 

Output

对于每个选手群,若你判断出产生了冠军,则在一行中输出“Yes”,否则在一行中输出“No”。

 

 

Sample Input

 

3 Alice Bob Smith John Alice Smith 5 a c c d d e b e a d 0

 

 

Sample Output

 

Yes No

 

 

对map应用的水题

//hdu 2094
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
#include
# include 
#include 

using namespace std;
#define ll long long int
const int inf = 0x3f3f3f3f;
const int maxn = 1e3 + 5;

int main(int argc, char  *argv[])
{
    int t, n, m;
    while(scanf("%d",&n) !=EOF&&n != 0)
    {

        map m;
        char str1[maxn], str2[maxn];
        int c = 1;
        for(int i = 0; i< n; i++)
        {
            scanf("%s%s", str1, str2);
            if(m.find(str1) == m.end())
            {
                m[str1] = true;
            }
            m[str2] = false;
        }
        int pp = 0;
        for(map::iterator it = m.begin(); it!= m.end(); it++)
        {
           if(it->second == 1)
           {
               pp++;

           }
        }
        if(pp == 1)
            printf("Yes\n");
        else
            printf("No\n");

    }
    return 0;
}

 

Arbitrage

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 11300    Accepted Submission(s): 5130


 

Problem Description

Arbitrage is the use of discrepancies in currency exchange rates to transform one unit of a currency into more than one unit of the same currency. For example, suppose that 1 US Dollar buys 0.5 British pound, 1 British pound buys 10.0 French francs, and 1 French franc buys 0.21 US dollar. Then, by converting currencies, a clever trader can start with 1 US dollar and buy 0.5 * 10.0 * 0.21 = 1.05 US dollars, making a profit of 5 percent.

Your job is to write a program that takes a list of currency exchange rates as input and then determines whether arbitrage is possible or not.

 

 

Input

The input file will contain one or more test cases. Om the first line of each test case there is an integer n (1<=n<=30), representing the number of different currencies. The next n lines each contain the name of one currency. Within a name no spaces will appear. The next line contains one integer m, representing the length of the table to follow. The last m lines each contain the name ci of a source currency, a real number rij which represents the exchange rate from ci to cj and a name cj of the destination currency. Exchanges which do not appear in the table are impossible.
Test cases are separated from each other by a blank line. Input is terminated by a value of zero (0) for n.

 

 

Output

For each test case, print one line telling whether arbitrage is possible or not in the format "Case case: Yes" respectively "Case case: No".

 

 

Sample Input

 

3 USDollar BritishPound FrenchFranc 3 USDollar 0.5 BritishPound BritishPound 10.0 FrenchFranc FrenchFranc 0.21 USDollar 3 USDollar BritishPound FrenchFranc 6 USDollar 0.5 BritishPound USDollar 4.9 FrenchFranc BritishPound 10.0 FrenchFranc BritishPound 1.99 USDollar FrenchFranc 0.09 BritishPound FrenchFranc 0.19 USDollar 0

 

 

Sample Output

 

Case 1: Yes Case 2: No

 

 

Source

用map离散一下

//hdu 1217
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
#include
# include 
#include 

using namespace std;
#define ll long long int
const int inf = 0x3f3f3f3f;
const int maxn = 1e2 + 5;
double book[maxn][maxn];
int dis[maxn];
void fun()
{
    memset(dis, false, sizeof(dis));
    for(int i = 0; i < maxn; i++)
    {
        for(int j = 0; j < maxn; j++)
        {
            if(i == j)
                book[i][j] = 1;
            else
                book[i][j] = 0;
        }
    }
}
int main(int argc, char  *argv[])
{
   // ios_base::sync_with_stdio(false);
    int t, n, m;
    int ca = 1;
    while(scanf("%d",&n) !=EOF, n)
    {
        fun();
   //     memset(book, false, sizeof(book));
        map mm;
        char str1[45], str2[45];
        int c = 1;
        for(int i = 1; i<= n; i++)
        {
            scanf("%s", str1);
            if(!mm[str1])
            {
                mm[str1] = c++;
            }
        }
        scanf("%d",&m);
        for(int i = 1; i <= m; i++)
        {
            double len ;
            scanf("%s%lf%s",str1,&len,str2);
            if(len > book[mm[str1]][mm[str2]])
            {
                book[mm[str1]][mm[str2]] = len;
            }
        }
    //    cout << c << "--" << n << endl;
        for(int k = 1; k <= n ; k++)
        {
            for(int i = 1; i <= n; i++)
            {
                if(book[i][k] < inf)
                {
                    for(int j = 1; j <= n; j++)
                    {
                        if(book[i][j] < book[i][k] * book[k][j])
                        {
                            book[i][j] = book[i][k] * book[k][j];
                        }
                    }
                }
            }
        }

        bool flag = false;
        for(int i =1; i <= n; i++)
        {

                if(book[i][i] > 1.0)
                {
                 //   cout << i << " " << j << " " << book[i][j] << endl;
                    flag = true;
                    break;
                }
        }

        printf("Case %d: ", ca++);
        if(flag)
        printf("Yes\n");
        else
            printf("No\n");

    }
    return 0;
}

Saving James Bond

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 4274    Accepted Submission(s): 921


 

Problem Description

This time let us consider the situation in the movie "Live and Let Die" in which James Bond, the world's most famous spy, was captured by a group of drug dealers. He was sent to a small piece of land at the center of a lake filled with crocodiles. There he performed the most daring action to escape -- he jumped onto the head of the nearest crocodile! Before the animal realized what was happening, James jumped again onto the next big head... Finally he reached the bank before the last crocodile could bite him (actually the stunt man was caught by the big mouth and barely escaped with his extra thick boot).
Assume that the lake is a 100×100 square one. Assume that the center of the lake is at (0,0) and the northeast corner at (50,50). The central island is a disk centered at (0,0) with the diameter of 15. A number of crocodiles are in the lake at various positions. Given the coordinates of each crocodile and the distance that James could jump, you must tell him whether he could escape.If he could,tell him the shortest length he has to jump and the min-steps he has to jump for shortest length.

 

 

Input

The input consists of several test cases. Each case starts with a line containing n <= 100, the number of crocodiles, and d > 0, the distance that James could jump. Then one line follows for each crocodile, containing the (x, y) location of the crocodile. Note that x and y are both integers, and no two crocodiles are staying at the same position.

 

 

Output

For each test case, if James can escape, output in one line the shortest length he has to jump and the min-steps he has to jump for shortest length. If it is impossible for James to escape that way, simply ouput "can't be saved".

 

 

Sample Input

 

4 10 17 0 27 0 37 0 45 0 1 10 20 30

 

 

Sample Output

 

42.50 5 can't be saved

 

 

//hdu 1245
#include 
#include 
#include 
#include 
using namespace std;
const double inf = 100000000;
double map[105][105];
int s[105],e[105],step[105][105],len1,len2;

struct node
{
    double x,y;
} a[105];

void floyd(int n)
{
    int i,j,k;
    for(k = 0; k<=n; k++)
        for(i = 0; i<=n; i++)
            for(j = 0; j<=n; j++)
                if(map[i][j]>map[i][k]+map[k][j])
                {
                    map[i][j]=map[i][k]+map[k][j];
                    step[i][j]=step[i][k]+step[k][j];
                }
}

int main()
{
    int n,i,j,k,len;
    double d,x,y;
    while(~scanf("%d%lf",&n,&d))
    {
        len = 1;
        for(i = 1; i<=n; i++)
        {
            scanf("%lf%lf",&x,&y);
            if(fabs(x)<=7.5 && fabs(y)<=7.5)//只将所有在小岛外的点存入图中
                continue;
            a[len].x = x;
            a[len++].y = y;
        }
        n = len;
        if(n == 1)//只存了一个点,直接判断
        {
            if(d>=42.5)
                printf("42.50 1\n");
            else
                printf("can't be saved\n");
            continue;
        }
        for(i = 0; i<=n; i++)
            for(j = 0; j<=n; j++)
            {
                map[i][j] = inf;
                step[i][j] = 0;
            }
        for(i = 1; id)//步伐不能到达,将该店变为无穷大
                {
                    map[i][j] = inf;
                    step[i][j] = 0;
                }
            }
        }
        len1 = len2 = 0;
        for(i = 1; i

Shortest Path

Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 6892    Accepted Submission(s): 1694


 

Problem Description

When YY was a boy and LMY was a girl, they trained for NOI (National Olympiad in Informatics) in GD team. One day, GD team’s coach, Prof. GUO asked them to solve the following shortest-path problem.
There is a weighted directed multigraph G. And there are following two operations for the weighted directed multigraph:
(1) Mark a vertex in the graph.
(2) Find the shortest-path between two vertices only through marked vertices.
For it was the first time that LMY faced such a problem, she was very nervous. At this moment, YY decided to help LMY to analyze the shortest-path problem. With the help of YY, LMY solved the problem at once, admiring YY very much. Since then, when LMY meets problems, she always calls YY to analyze the problems for her. Of course, YY is very glad to help LMY. Finally, it is known to us all, YY and LMY become programming lovers.
Could you also solve the shortest-path problem?

 

 

Input

The input consists of multiple test cases. For each test case, the first line contains three integers N, M and Q, where N is the number of vertices in the given graph, N≤300; M is the number of arcs, M≤100000; and Q is the number of operations, Q ≤100000. All vertices are number as 0, 1, 2, … , N - 1, respectively. Initially all vertices are unmarked. Each of the next M lines describes an arc by three integers (x, y, c): initial vertex (x), terminal vertex (y), and the weight of the arc (c). (c > 0) Then each of the next Q lines describes an operation, where operation “0 x” represents that vertex x is marked, and operation “1 x y” finds the length of shortest-path between x and y only through marked vertices. There is a blank line between two consecutive test cases.
End of input is indicated by a line containing N = M = Q = 0.

 

 

Output

Start each test case with "Case #:" on a single line, where # is the case number starting from 1.
For operation “0 x”, if vertex x has been marked, output “ERROR! At point x”.
For operation “1 x y”, if vertex x or vertex y isn’t marked, output “ERROR! At path x to y”; if y isn’t reachable from x through marked vertices, output “No such path”; otherwise output the length of the shortest-path. The format is showed as sample output.
There is a blank line between two consecutive test cases.

 

 

Sample Input

 

5 10 10 1 2 6335 0 4 5725 3 3 6963 4 0 8146 1 2 9962 1 0 1943 2 1 2392 4 2 154 2 2 7422 1 3 9896 0 1 0 3 0 2 0 4 0 4 0 1 1 3 3 1 1 1 0 3 0 4 0 0 0

 

 

Sample Output

 

Case 1: ERROR! At point 4 ERROR! At point 1 0 0 ERROR! At point 3 ERROR! At point 4

 

 

Source

 

对于K的理解加深了是松弛了K个城市,也可以单个松弛,当前编号为k

//hdu 3631
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
#include
# include 
#include 

using namespace std;
#define ll long long int
const int inf = 0x3f3f3f3f;
const int maxn = 3e2 + 5;
int book[maxn][maxn];
int h[maxn];
int n;
void fun()
{
    memset(h, false, sizeof(h));
    for(int i = 0; i < maxn; i++)
    {
        for(int j = 0; j < maxn; j++)
        {
            if(i == j)
                book[i][j] = 0;
            else
                book[i][j] = inf;
        }
    }
}
void floyd(int k)
{
    for(int i = 0; i < n; i++)
    {
        if(book[i][k] != inf)
        for(int j = 0; j < n; j++)
        {
            if(book[k][j] != inf &&book[i][j] > book[i][k] + book[k][j])
                book[i][j] = book[i][k] + book[k][j];
        }
    }
}
int main(int argc, char  *argv[])
{
   // ios_base::sync_with_stdio(false);
    int  m, q;
    int ca = 1;
    while(scanf("%d%d%d",&n, &m, &q) !=EOF, n||q ||m)
    {
        fun();
        for(int i = 0; i < m; i++)
        {
            int x, y, len;
            scanf("%d%d%d",&x, &y, &len);
            if(book[x][y] > len)
            {
                book[x][y] = len;
            }
        }
         if(ca!=1)
            printf("\n");
        printf("Case %d:\n", ca++);
        for(int i = 0; i < q; i++)
        {
            int flag;
            scanf("%d",&flag);
            if(!flag)
            {
                int x;
                scanf("%d",&x);
                if(!h[x])
                {
                    h[x] = 1;
                    floyd(x);
                }
                else
                {
                   printf("ERROR! At point %d\n",x);
                }
            }
            else
            {
                int x, y;
                scanf("%d%d",&x, &y);
                if(h[x]&&h[y])
                {
                   if(book[x][y]< inf)
                   {
                       printf("%d\n",book[x][y]);
                   }
                   else
                   {
                       printf("No such path\n");
                   }
                }
                else
                {
                    printf("ERROR! At path %d to %d\n",x,y);
                }
            }
        }
    }
    return 0;
}

Travel

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 5210    Accepted Submission(s): 1405


 

Problem Description

  PP loves travel. Her dream is to travel around country A which consists of N cities and M roads connecting them. PP has measured the money each road costs. But she still has one more problem: she doesn't have enough money. So she must work during her travel. She has chosen some cities that she must visit and stay to work. In City_i she can do some work to earn Ci money, but before that she has to pay Di money to get the work license. She can't work in that city if she doesn't get the license but she can go through the city without license. In each chosen city, PP can only earn money and get license once. In other cities, she will not earn or pay money so that you can consider Ci=Di=0. Please help her make a plan to visit all chosen cities and get license in all of them under all rules above.
  PP lives in city 1, and she will start her journey from city 1. and end her journey at city 1 too.

 

 

Input

  The first line of input consists of one integer T which means T cases will follow.
  Then follows T cases, each of which begins with three integers: the number of cities N (N <= 100) , number of roads M (M <= 5000) and her initiative money Money (Money <= 10^5) .
  Then follows M lines. Each contains three integers u, v, w, which means there is a road between city u and city v and the cost is w. u and v are between 1 and N (inclusive), w <= 10^5.
  Then follows a integer H (H <= 15) , which is the number of chosen cities.
  Then follows H lines. Each contains three integers Num, Ci, Di, which means the i_th chosen city number and Ci, Di described above.(Ci, Di <= 10^5)

 

 

Output

  If PP can visit all chosen cities and get all licenses, output "YES", otherwise output "NO".

 

 

Sample Input

 

2 4 5 10 1 2 1 2 3 2 1 3 2 1 4 1 3 4 2 3 1 8 5 2 5 2 3 10 1 2 1 100 1 2 10000 1 2 100000 1

 

 

Sample Output

 

YES NO

//先用最短路预处理完之后在爆搜就可以

//hdu 2544
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
# include 
#include
# include 
#include 

using namespace std;
#define ll long long int
const int inf = 0x3f3f3f3f;
const int maxn = 1e3 + 5;
int book[maxn][maxn];
int dis[maxn];
int n, m, money, h;
bool flag;
void fun()
{
    flag = false;
    memset(dis, false, sizeof(dis));
    for(int i = 0; i < maxn; i++)
    {
        for(int j = 0; j < maxn; j++)
        {
            if(i == j)
                book[i][j] = 0;
            else
                book[i][j] = inf;
        }
    }
}

struct node
{
    int num, ci, di;
}s[maxn];

void dfs(int x, int z, int ff)
{
    if(flag)
        return ;
    if(z == h)
    {
        if(ff - book[x][1] >= 0)
            flag = true;
        return ;
    }
    for(int i = 0; i < h; i++)
    {
        if(book[x][s[i].num] != inf && ff - book[x][s[i].num] >= s[i].di)
        {
            if(!dis[s[i].num])
            {
                dis[s[i].num] = true;
                dfs(s[i].num, z + 1, ff - book[x][s[i].num] - s[i].di + s[i].ci);
                dis[s[i].num] = false;
            }
        }
    }
}

int main(int argc, char  *argv[])
{
   // ios_base::sync_with_stdio(false);
    int t;
    while(scanf("%d",&t) != EOF)
    {
        while(t--)
        {
            fun();
            scanf("%d%d%d",&n, &m, &money);

            for(int i = 1; i <= m; i++)
            {
                int x, y, len;
                scanf("%d%d%d",&x,&y,&len);
                if(len < book[x][y])
                {
                    book[y][x] = book[x][y] = len;
                }
            }
            for(int k = 1; k <= n; k++)
            {
                for(int i = 1; i <= n; i++)
                {
                    if(book[i][k] != inf)
                    {
                        for(int j = 1; j <= n; j++)
                        {
                            if(book[i][j] > book[i][k] + book[k][j])
                            {
                                book[i][j] = book[i][k] + book[k][j];
                                book[j][i] = book[i][j];
                            }
                        }
                    }
                }
            }
            scanf("%d",&h);
            for(int i = 0; i < h; i++)
                scanf("%d%d%d",&s[i].num,&s[i].ci,&s[i].di);
            dfs(1, 0, money);

            if(flag)
            {
                printf("YES\n");
            }
            else
            {
                printf("NO\n");
            }

        }
    }
    return 0;
}

find the mincost route

Time Limit: 1000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 8149    Accepted Submission(s): 3084


 

Problem Description

杭州有N个景区,景区之间有一些双向的路来连接,现在8600想找一条旅游路线,这个路线从A点出发并且最后回到A点,假设经过的路线为V1,V2,....VK,V1,那么必须满足K>2,就是说至除了出发点以外至少要经过2个其他不同的景区,而且不能重复经过同一个景区。现在8600需要你帮他找一条这样的路线,并且花费越少越好。

 

 

Input

第一行是2个整数N和M(N <= 100, M <= 1000),代表景区的个数和道路的条数。
接下来的M行里,每行包括3个整数a,b,c.代表a和b之间有一条通路,并且需要花费c元(c <= 100)。

 

 

Output

对于每个测试实例,如果能找到这样一条路线的话,输出花费的最小值。如果找不到的话,输出"It's impossible.".

 

 

Sample Input

 

3 3 1 2 1 2 3 1 1 3 1 3 3 1 2 1 1 2 3 2 3 1

 

 

Sample Output

 

3 It's impossible.

 

 

Author

8600

对于K的理解更加深刻,可以用来处理最小环

//hdu 1599
#include 
#include 
#include 
using namespace std;
const int maxn = 110;
const int inf = 1000000;
int dist[maxn][maxn];
int e[maxn][maxn];
int n,m;
void initial()
{
    int i;
    int j;
    for(i = 1 ; i <= n ; ++i)
    {
        for(j = 1 ; j <= n ; ++j)
        {
            if(i == j)
                e[i][j] = 0;
            else
                e[i][j] = inf;
        }
    }
}

int floyd()
{
    int i;
    int j;
    int k;

    int mincircle = inf;
//  dist = e;
    for(i = 1 ; i <= n ; ++i)
    {
        for(j = 1 ; j <= n ; ++j)
        {
            dist[i][j] = e[i][j];
        }
    }

    //根据Floyed的原理,在最外层循环做了k-1次之后,dis[i][j]则代表了i到j的路径中所有结点编号都小于k的最短路径
    for(k = 1 ; k <= n ; ++k)
    {
        //环的最小长度为edge[i][k]+edge[k][j]+i->j的路径中所有编号小于k的最短路径长度
        for(i = 1 ; i < k ; ++i)
            for(j = i+1 ; j < k ; ++j)
                if(dist[i][j] + e[i][k] + e[k][j] < inf)
                    mincircle = min(mincircle,dist[i][j] + e[j][k] + e[k][i]);
        //floyd原来的部分,更新dist[i][j]
        for(i = 1 ; i <= n ; ++i)
            for(j = 1 ; j <= n ; ++j)
                if(dist[i][j] > dist[i][k] + dist[k][j])
                    dist[i][j] = dist[i][k] + dist[k][j];

    }
    return mincircle;
}

int main()
{
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        initial();
        int i;
        for(i = 1 ; i <= m ; ++i)
        {
            int a,b,c;
            scanf("%d%d%d",&a,&b,&c);
            if(e[a][b] > c)
                e[a][b] = e[b][a] = c;
        }
        int ans = floyd();
        if(ans != inf)
            printf("%d\n",ans);
        else
            printf("It's impossible.\n");
    }
    return 0;
}

 

你可能感兴趣的:(ACM算法题,动态规划,图论)