Kuangbin专题四最短路练习

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_40379678/article/details/81539175

刷了两天半终于百度完了所有题。什么时候能自己写出题目。Orz,太菜了。

A - Til the Cows Come Home

 POJ - 2387 

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.

板子题,我dijkstra板子用了堆优化,所以没有判断重边。

#include <cstdio>
#include <cstring>
#include <utility>
#include <iostream>
#include <map>
#include <queue>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
using namespace std;
typedef pair<int, int> P;
typedef long long ll;
#define N 11000
#define M 3645
const int INF = 0x3f3f3f3f;
const double eps = 1e-5;
const double PI = acos(-1);
#define fi first
#define se second
#define rep(i, lll, nnn) for(int i = (lll); i <= (nnn); i++)

int t, n;
struct edge{
  int v, w;
};
vector<edge> G[N];
int d[N];

void dijkstra()
{
    priority_queue< P, vector<P>, greater<P> > que;
    memset(d, INF, sizeof d);
    d[n] = 0;
    que.push(P(0, n));

    while(!que.empty()) {
        P h = que.top(); que.pop();

        int v = h.se;
        if(d[v] < h.fi) continue;

        for(int i = 0; i < G[v].size(); i++) {
            edge e = G[v][i];
            if(d[e.v] > d[v] + e.w)
                d[e.v] = d[v] + e.w, que.push(P(d[e.v], e.v));
        }
    }
}

int main()
{
    #ifndef ONLINE_JUDGE
    freopen("data.txt", "r", stdin);
    #endif

    scanf("%d%d", &t, &n);

    int u, v, w;
    edge e;
    rep(i, 1, t) {
        scanf("%d%d%d", &u, &v, &w);
        e.v = v; e.w = w;
        G[u].push_back(e);
        e.v = u;
        G[v].push_back(e);
    }

    dijkstra();

    printf("%d\n", d[1]);

    return 0;
}

B - Frogger

 POJ - 2253 

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

要求所有路中的最短的最长边是多少。

这题和最短路扯上关系有点难想。d[u]表示从1到u的路中最长边,那么就能松弛:d[v] = min(d[v], max(d[u], g[u][v]));

dijkstra求最短路是每次从已经确定d的集合中选出d值最小的来松弛,路的权值是所有边的权值和,求的是权值最小的路;这里也是从已经确定d的集合中选出d值最小的来松弛,路的权值是这条路中最长的边,求的也是权值最小的路。

#include <cstdio>
#include <cstring>
#include <utility>
#include <iostream>
#include <map>
#include <queue>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
using namespace std;
typedef pair<double, int> P;
typedef long long ll;
#define N 210
#define M 3645
const int INF = 0x3f3f3f3f;
const double eps = 1e-5;
const double PI = acos(-1);
#define fi first
#define se second
#define rep(i, lll, nnn) for(int i = (lll); i <= (nnn); i++)

int t, n;
double dis[N][N];
P ps[N];
double d[N];

void dijkstra()
{
    fill(d, d + N, INF);
    d[1] = 0;

    priority_queue<P, vector<P>, greater<P> > que;
    que.push(P(0.0, 1));

    while(!que.empty()) {
        P h = que.top(); que.pop();
        int v = h.se;
        //if(d[v] < h.fi) continue;

        for(int i = 1; i <= n; i++) {
            double tmp = max(d[v], dis[v][i]);
            if(d[i] > tmp) {
                d[i] = tmp;
                que.push(P(d[i], i));
            }
        }
    }
}

int main()
{
    #ifndef ONLINE_JUDGE
    freopen("data.txt", "r", stdin);
    #endif

    while(~scanf("%d", &n) && n) {
        rep(i, 1, n) scanf("%lf%d", &ps[i].fi, &ps[i].se);
        rep(i, 1, n) rep(j, 1, n) {
            double dx = ps[i].fi - ps[j].fi;
            double dy = ps[i].se - ps[j].se;
            dis[i][j] = dx * dx + dy * dy;
            dis[i][j] = sqrt(dis[i][j]);
        }
        dijkstra();
        if(t) puts("");
        printf("Scenario #%d\nFrog Distance = %.3f\n", ++t, d[2]);
    }

    return 0;
}

C - Heavy Transportation

 POJ - 1797

Background 
Hugo Heavy is happy. After the breakdown of the Cargolifter project he can now expand business. But he needs a clever man who tells him whether there really is a way from the place his customer has build his giant steel crane to the place where it is needed on which all streets can carry the weight. 
Fortunately he already has a plan of the city with all streets and bridges and all the allowed weights.Unfortunately he has no idea how to find the the maximum weight capacity in order to tell his customer how heavy the crane may become. But you surely know. 

Problem 
You are given the plan of the city, described by the streets (with weight limits) between the crossings, which are numbered from 1 to n. Your task is to find the maximum weight that can be transported from crossing 1 (Hugo's place) to crossing n (the customer's place). You may assume that there is at least one path. All streets can be travelled in both directions.

Input

The first line contains the number of scenarios (city plans). For each city the number n of street crossings (1 <= n <= 1000) and number m of streets are given on the first line. The following m lines contain triples of integers specifying start and end crossing of the street and the maximum allowed weight, which is positive and not larger than 1000000. There will be at most one street between each pair of crossings.

Output

The output for every scenario begins with a line containing "Scenario #i:", where i is the number of the scenario starting at 1. Then print a single line containing the maximum allowed weight that Hugo can transport to the customer. Terminate the output for the scenario with a blank line.

Sample Input

1
3 3
1 2 3
1 3 4
2 3 5

Sample Output

Scenario #1:
4

和上一题一样,只不过反过来了。

#include <cstdio>
#include <cstring>
#include <utility>
#include <iostream>
#include <map>
#include <queue>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
using namespace std;
typedef pair<int, int> P;
typedef long long ll;
#define N 1010
#define M 3645
const int INF = 0x3f3f3f3f;
const double eps = 1e-5;
const double PI = acos(-1);
#define fi first
#define se second
#define rep(i, lll, nnn) for(int i = (lll); i <= (nnn); i++)

int t, n, m, u, v, w;
int dis[N][N];
bool vis[N];
int d[N];

void dijkstra()
{
    memset(vis, false, sizeof vis);
    memset(d, 0, sizeof d);
    rep(i, 1, n) d[i] = dis[1][i];
    vis[1] = true;

    rep(i, 1, n) {
        int maxn = 0, p;
        rep(j, 1, n)  {
            if(!vis[j] && d[j] > maxn) {
                maxn = d[j];
                p = j;
            }
        }

        vis[p] = true;
        rep(k, 1, n) {
            d[k] = max(d[k], min(d[p], dis[p][k]));
        }
    }
}

int main()
{
    #ifndef ONLINE_JUDGE
    freopen("data.txt", "r", stdin);
    #endif

    scanf("%d", &t);

    rep(Case, 1, t) {
        scanf("%d%d", &n, &m);
        rep(i, 1, n) rep(j, 1, n) dis[i][j] = 0;
        rep(i, 1, m) {
            scanf("%d%d%d", &u, &v, &w);
            dis[u][v] = max(dis[u][v], w);
            dis[v][u] = max(dis[v][u], w);
        }

        dijkstra();

        printf("Scenario #%d:\n%d\n\n", Case, d[n]);
    }

    return 0;
}

D - Silver Cow Party

 POJ - 3268

One cow from each of N farms (1 ≤ N ≤ 1000) conveniently numbered 1..N is going to attend the big cow party to be held at farm #X (1 ≤ X ≤ N). A total of M (1 ≤ M≤ 100,000) unidirectional (one-way roads connects pairs of farms; road i requires Ti (1 ≤ Ti ≤ 100) units of time to traverse.

Each cow must walk to the party and, when the party is over, return to her farm. Each cow is lazy and thus picks an optimal route with the shortest time. A cow's return route might be different from her original route to the party since roads are one-way.

Of all the cows, what is the longest amount of time a cow must spend walking to the party and back?

Input

Line 1: Three space-separated integers, respectively: NM, and X 
Lines 2.. M+1: Line i+1 describes road i with three space-separated integers: Ai,Bi, and Ti. The described road runs from farm Ai to farm Bi, requiring Ti time units to traverse.

Output

Line 1: One integer: the maximum of time any one cow must walk.

Sample Input

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

Sample Output

10

Hint

Cow 4 proceeds directly to the party (3 units) and returns via farms 1 and 3 (7 units), for a total of 10 time units.

这题我看数据量直接对每个点跑了个nlogn的dijkstra,复杂度是n^2longn,没超时哈哈哈哈。。。其实现在写博客觉得可以反过来建图,就是原来(u, v, w)变成(v, u, w)。然后跑两遍就行了。

注释的是n^2logn的代码过了哈哈哈哈哈哈哈。

#include <cstdio>
#include <cstring>
#include <utility>
#include <iostream>
#include <map>
#include <queue>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
using namespace std;
typedef pair<int, int> P;
typedef long long ll;
#define N 1010
#define M 100010
const int INF = 0x3f3f3f3f;
const double eps = 1e-5;
const double PI = acos(-1);
#define fi first
#define se second
#define rep(i, lll, nnn) for(int i = (lll); i <= (nnn); i++)

int n, m, x, a[M], b[M], c[M], ans;
int d[N], d1[N], d2[N];
struct Edge {
  int v, w;
}e;
vector<Edge> G[N];
priority_queue<P, vector<P>, greater<P> > que;

void dijkstra()
{
    memset(d, INF, sizeof d);
    while(!que.empty()) que.pop();
    que.push(P(0, x));
    d[x] = 0;

    while(!que.empty()) {
        P h = que.top(); que.pop();

        if(d[h.se] < h.fi) continue;

        for(int i = 0; i < G[h.se].size(); i++) {
            Edge & e = G[h.se][i];
            if(d[e.v] > d[h.se] + e.w) {
                d[e.v] = d[h.se] + e.w;
                que.push(P(d[e.v], e.v));
            }
        }
    }
}

int main()
{
    #ifndef ONLINE_JUDGE
    freopen("data.txt", "r", stdin);
    #endif

    while(~scanf("%d%d%d", &n, &m, &x)) {
        rep(i, 1, n) G[i].clear();
        rep(i, 1, m) {
            scanf("%d%d%d", &a[i], &b[i], &c[i]);
            e.v = b[i]; e.w = c[i];
            G[a[i]].push_back(e);
        }
        dijkstra();
        memcpy(d1, d, sizeof d);

        rep(i, 1, n) G[i].clear();
        rep(i, 1, m) {
            e.v = a[i]; e.w = c[i];
            G[b[i]].push_back(e);
        }
        dijkstra();
        memcpy(d2, d, sizeof d);

        ans = 0;
        rep(i, 1, n) ans = max(ans, d1[i] + d2[i]);

        printf("%d\n", ans);
    }

    return 0;
}

//#include <cstdio>
//#include <cstring>
//#include <utility>
//#include <iostream>
//#include <map>
//#include <queue>
//#include <algorithm>
//#include <cmath>
//#include <string>
//#include <vector>
//using namespace std;
//typedef pair<int, int> P;
//typedef long long ll;
//#define N 1010
//#define M 3645
//const int INF = 0x3f3f3f3f;
//const double eps = 1e-5;
//const double PI = acos(-1);
//#define fi first
//#define se second
//#define rep(i, lll, nnn) for(int i = (lll); i <= (nnn); i++)
//
//int n, m, x, a, b, c, ans;
//int d[N][N];
//struct Edge {
//  int v, w;
//}e;
//vector<Edge> G[N];
//priority_queue<P, vector<P>, greater<P> > que;
//
//void dijkstra(int s)
//{
//    memset(d[s], INF, sizeof d[s]);
//    while(!que.empty()) que.pop();
//    que.push(P(0, s));
//    d[s][s] = 0;
//
//    while(!que.empty()) {
//        P h = que.top(); que.pop();
//
//        if(d[s][h.se] < h.fi) continue;
//
//        for(int i = 0; i < G[h.se].size(); i++) {
//            Edge & e = G[h.se][i];
//            if(d[s][e.v] > d[s][h.se] + e.w) {
//                d[s][e.v] = d[s][h.se] + e.w;
//                que.push(P(d[s][e.v], e.v));
//            }
//        }
//    }
//}
//
//int main()
//{
//    #ifndef ONLINE_JUDGE
//    freopen("data.txt", "r", stdin);
//    #endif
//
//    while(~scanf("%d%d%d", &n, &m, &x)) {
//        rep(i, 1, n) G[i].clear();
//        rep(i, 1, m) {
//            scanf("%d%d%d", &a, &b, &c);
//            e.v = b; e.w = c;
//            G[a].push_back(e);
//        }
//
//        rep(i, 1, n) dijkstra(i);
//
//        ans = 0;
//        rep(i, 1, n) ans = max(ans, d[i][x] + d[x][i]);
//
//        printf("%d\n", ans);
//    }
//
//    return 0;
//}

E - Currency Exchange

 POJ - 1860

Several currency exchange points are working in our city. Let us suppose that each point specializes in two particular currencies and performs exchange operations only with these currencies. There can be several points specializing in the same pair of currencies. Each point has its own exchange rates, exchange rate of A to B is the quantity of B you get for 1A. Also each exchange point has some commission, the sum you have to pay for your exchange operation. Commission is always collected in source currency. 
For example, if you want to exchange 100 US Dollars into Russian Rubles at the exchange point, where the exchange rate is 29.75, and the commission is 0.39 you will get (100 - 0.39) * 29.75 = 2963.3975RUR. 
You surely know that there are N different currencies you can deal with in our city. Let us assign unique integer number from 1 to N to each currency. Then each exchange point can be described with 6 numbers: integer A and B - numbers of currencies it exchanges, and real R AB, C AB, R BA and C BA - exchange rates and commissions when exchanging A to B and B to A respectively. 
Nick has some money in currency S and wonders if he can somehow, after some exchange operations, increase his capital. Of course, he wants to have his money in currency S in the end. Help him to answer this difficult question. Nick must always have non-negative sum of money while making his operations. 

Input

The first line of the input contains four numbers: N - the number of currencies, M - the number of exchange points, S - the number of currency Nick has and V - the quantity of currency units he has. The following M lines contain 6 numbers each - the description of the corresponding exchange point - in specified above order. Numbers are separated by one or more spaces. 1<=S<=N<=100, 1<=M<=100, V is real number, 0<=V<=10 3. 
For each point exchange rates and commissions are real, given with at most two digits after the decimal point, 10 -2<=rate<=10 2, 0<=commission<=10 2. 
Let us call some sequence of the exchange operations simple if no exchange point is used more than once in this sequence. You may assume that ratio of the numeric values of the sums at the end and at the beginning of any simple sequence of the exchange operations will be less than 10 4. 

Output

If Nick can increase his wealth, output YES, in other case output NO to the output file.

Sample Input

3 2 1 20.0
1 2 1.00 1.00 1.00 1.00
2 3 1.10 1.00 1.10 1.00

Sample Output

YES

只有判断负环的板子,,,,没想到还能判断正环,差不多,都是松弛。

用Bellman和Floyed各写了一个,Spfa也能写。

#include <cstdio>
#include <cstring>
#include <utility>
#include <iostream>
#include <map>
#include <queue>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
using namespace std;
typedef pair<int, int> P;
typedef long long ll;
#define N 110
#define M 3645
const int INF = 0x3f3f3f3f;
const double eps = 1e-5;
const double PI = acos(-1);
#define fi first
#define se second
#define rep(i, lll, nnn) for(int i = (lll); i <= (nnn); i++)

int n, m, s;
double v;
int a, b;
double r1, c1, r2, c2;
struct Cost{
  double r, c;
  Cost (double r = 0.0, double c = 0.0):r(r), c(c){}
}cost[N][N];
vector<int> G[N];
double d[N];
bool vis[N];

double go(double sum, int x, int y){
    return (sum - cost[x][y].c) * cost[x][y].r;
}

//bool solve()
//{
//    fill(d, d + N, 0);
//    d[s] = v;
//
//    rep(k, 1, n) {
//        bool flag = false;
//        rep(i, 1, n)
//        for(int j = 0; j < G[i].size(); j++) {
//            int v = G[i][j];
//            if(d[v] < go(d[i], i, v)) {
//                d[v] = go(d[i], i, v);
//                flag = true;
//            }
//        }
//        if(!flag) return false;
//        if(k == n) return true;
//    }
//
//    return false;
//}

bool solve()
{
    fill(d, d + N, 0);
    d[s] = v;

    rep(k, 1, n) rep(i, 1, n) rep(j, 1, n) {
        d[j] = max(d[j], go(d[i], i, j));
    }

    rep(i, 1, n) for(int j = 0; j < G[i].size(); j++) {
        int v = G[i][j];
        if(d[v] < go(d[i], i, v))
            return true;
    }

    return false;
}

int main()
{
    #ifndef ONLINE_JUDGE
    freopen("data.txt", "r", stdin);
    #endif

    while(~scanf("%d%d%d%lf", &n, &m, &s, &v)) {
        memset(cost, 0, sizeof cost);
        rep(i, 1, n) G[i].clear();
        rep(i, 1, m) {
            scanf("%d%d%lf%lf%lf%lf", &a, &b, &r1, &c1, &r2, &c2);
            cost[a][b].r = r1; cost[a][b].c = c1;
            cost[b][a].r = r2; cost[b][a].c = c2;
            G[a].push_back(b); G[b].push_back(a);
        }

        printf(solve()?"YES\n":"NO\n");
    }

    return 0;
}

F - Wormholes

 POJ - 3259

While exploring his many farms, Farmer John has discovered a number of amazing wormholes. A wormhole is very peculiar because it is a one-way path that delivers you to its destination at a time that is BEFORE you entered the wormhole! Each of FJ's farms comprises N (1 ≤ N ≤ 500) fields conveniently numbered 1..NM (1 ≤ M≤ 2500) paths, and W (1 ≤ W ≤ 200) wormholes.

As FJ is an avid time-traveling fan, he wants to do the following: start at some field, travel through some paths and wormholes, and return to the starting field a time before his initial departure. Perhaps he will be able to meet himself :) .

To help FJ find out whether this is possible or not, he will supply you with complete maps to F (1 ≤ F ≤ 5) of his farms. No paths will take longer than 10,000 seconds to travel and no wormhole can bring FJ back in time by more than 10,000 seconds.

Input

Line 1: A single integer, FF farm descriptions follow. 
Line 1 of each farm: Three space-separated integers respectively: NM, and W 
Lines 2.. M+1 of each farm: Three space-separated numbers ( SET) that describe, respectively: a bidirectional path between S and E that requires T seconds to traverse. Two fields might be connected by more than one path. 
Lines M+2.. MW+1 of each farm: Three space-separated numbers ( SET) that describe, respectively: A one way path from S to E that also moves the traveler backT seconds.

Output

Lines 1.. F: For each farm, output "YES" if FJ can achieve his goal, otherwise output "NO" (do not include the quotes).

Sample Input

2
3 3 1
1 2 2
1 3 4
2 3 1
3 1 3
3 2 1
1 2 3
2 3 4
3 1 8

Sample Output

NO
YES

Hint

For farm 1, FJ cannot travel back in time. 
For farm 2, FJ could travel back in time by the cycle 1->2->3->1, arriving back at his starting location 1 second before he leaves. He could start from anywhere on the cycle to accomplish this.

找负环的板子题。

#include <cstdio>
#include <cstring>
#include <utility>
#include <iostream>
#include <map>
#include <queue>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
using namespace std;
typedef pair<int, int> P;
typedef long long ll;
#define N 510
#define M 3645
const int INF = 0x3f3f3f3f;
const double eps = 1e-5;
const double PI = acos(-1);
#define fi first
#define se second
#define rep(i, lll, nnn) for(int i = (lll); i <= (nnn); i++)

int t, n, m, w;
struct Edge {
  int v, w;
};
vector<Edge> G[N];
int d[N];

bool solve()
{
    memset(d, 0, sizeof d);

    rep(k, 1, n) {
        rep(i, 1, n) {
            for(int j = 0; j < G[i].size(); j++) {
                Edge & e = G[i][j];
                if(d[e.v] > d[i] + e.w) {
                    d[e.v] = d[i] + e.w;
                    if(k == n) return true;
                }
            }
        }
    }
    return false;
}

int main()
{
    #ifndef ONLINE_JUDGE
     freopen("data.txt", "r", stdin);
    #endif

    scanf("%d", &t);
    while(t--) {
        scanf("%d%d%d", &n, &m, &w);
        rep(i, 1, n) G[i].clear();
        Edge e;
        int u;
        rep(i, 1, m) {
            scanf("%d%d%d", &u, &e.v, &e.w);
            G[u].push_back(e);
            swap(u, e.v);
            G[u].push_back(e);
        }
        rep(i, 1, w) {
            scanf("%d%d%d", &u, &e.v, &e.w);
            e.w = -e.w;
            G[u].push_back(e);
        }

        printf(solve()?"YES\n":"NO\n");
    }

    return 0;
}

G - MPI Maelstrom

 POJ - 1502

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
#include <cstdio>
#include <cstring>
#include <utility>
#include <iostream>
#include <map>
#include <queue>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
using namespace std;
typedef pair<int, int> P;
typedef long long ll;
#define N 11000
#define M 3645
const int INF = 0x3f3f3f3f;
const double eps = 1e-5;
const double PI = acos(-1);
#define fi first
#define se second
#define rep(i, lll, nnn) for(int i = (lll); i <= (nnn); i++)

int t, n;
struct edge{
  int v, w;
};
vector<edge> G[N];
int d[N];

void dijkstra()
{
    priority_queue< P, vector<P>, greater<P> > que;
    memset(d, INF, sizeof d);
    d[n] = 0;
    que.push(P(0, n));

    while(!que.empty()) {
        P h = que.top(); que.pop();

        int v = h.se;
        if(d[v] < h.fi) continue;

        for(int i = 0; i < G[v].size(); i++) {
            edge e = G[v][i];
            if(d[e.v] > d[v] + e.w)
                d[e.v] = d[v] + e.w, que.push(P(d[e.v], e.v));
        }
    }
}

int getn()
{
    char ch = 'x';
    cin >> ch;
    if(ch == 'x') return -1;
    int ret = ch - '0';
    while((ch = getchar()) != ' ' && ch != '\n' && ch != EOF) {
        ret = ret * 10 + ch - '0';
    }
    return ret;
}

int main()
{
    #ifndef ONLINE_JUDGE
    freopen("data.txt", "r", stdin);
    #endif

    scanf("%d", &n);

    int w;
    edge e;
    rep(i, 2, n) rep(j, 1, i - 1){
        if((w = getn()) > 0) {
            e.v = j; e.w = w;
            G[i].push_back(e);
            e.v = i;
            G[j].push_back(e);
        }
    }

    dijkstra();
    int ans = 0;
    rep(i, 2, n) ans = max(ans, d[i]);

    printf("%d\n", ans);

    return 0;
}

H - Cow Contest

 POJ - 3660

N (1 ≤ N ≤ 100) cows, conveniently numbered 1..N, are participating in a programming contest. As we all know, some cows code better than others. Each cow has a certain constant skill rating that is unique among the competitors.

The contest is conducted in several head-to-head rounds, each between two cows. If cow A has a greater skill level than cow B (1 ≤ A ≤ N; 1 ≤ B ≤ NA ≠ B), then cow A will always beat cow B.

Farmer John is trying to rank the cows by skill level. Given a list the results of M(1 ≤ M ≤ 4,500) two-cow rounds, determine the number of cows whose ranks can be precisely determined from the results. It is guaranteed that the results of the rounds will not be contradictory.

Input

* Line 1: Two space-separated integers: N and M
* Lines 2..M+1: Each line contains two space-separated integers that describe the competitors and results (the first integer, A, is the winner) of a single round of competition: A and B

Output

* Line 1: A single integer representing the number of cows whose ranks can be determined
 

Sample Input

5 5
4 3
4 2
3 2
1 2
2 5

Sample Output

2

一个点能不能确定要看它和所有其它点之间有没有确定关系,而所有点之间的关系可以Floyed来求。

#include <cstdio>
#include <cstring>
#include <utility>
#include <iostream>
#include <map>
#include <queue>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
using namespace std;
typedef pair<int, int> P;
typedef long long ll;
#define N 110
#define M 3645
const int INF = 0x3f3f3f3f;
const double eps = 1e-5;
const double PI = acos(-1);
#define fi first
#define se second
#define rep(i, lll, nnn) for(int i = (lll); i <= (nnn); i++)

int n, m, a, b;
bool g[N][N];

int main()
{
    #ifndef ONLINE_JUDGE
    freopen("data.txt", "r", stdin);
    #endif

    while(~scanf("%d%d", &n, &m)) {
        rep(i, 1, m) {
            scanf("%d%d", &a, &b);
            g[a][b] = true;
        }

        rep(k, 1, n) rep(i, 1, n) rep(j, 1, n) {
            g[i][j] = g[i][j]|(g[i][k]&g[k][j]);
        }

        int ans = 0;
        rep(i, 1, n) {
            int ret = 0;
            rep(j, 1, n) ret += g[i][j]|g[j][i];
            if(ret == n - 1) ans++;
        }

        printf("%d\n", ans);
    }

    return 0;
}

I - Arbitrage

 POJ - 2240

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 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

判断正环。

#include <cstdio>
#include <cstring>
#include <utility>
#include <iostream>
#include <map>
#include <queue>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
using namespace std;
typedef pair<int, int> P;
typedef long long ll;
#define N 40
#define M 3645
const int INF = 0x3f3f3f3f;
const double eps = 1e-6;
const double PI = acos(-1);
#define fi first
#define se second
#define rep(i, lll, nnn) for(int i = (lll); i <= (nnn); i++)

int n, m;
map<string, int> mp;
string c1, c2, c;
double r, g[N][N];
double d[N];

bool solve()
{
    memset(d, 0, sizeof d);
    d[1] = 1;

    rep(k, 1, n) {
        rep(i, 1, n) rep(j, 1, n) if(g[i][j] > eps) {
            if(d[j] < d[i] * g[i][j]) {
                d[j] = d[i] * g[i][j];
                if(k == n) return true;
            }
        }
    }
    return false;
}

int main()
{
    #ifndef ONLINE_JUDGE
    freopen("data.txt", "r", stdin);
    #endif

    int t = 0;
    while(~scanf("%d", &n) && n) {
        rep(i, 1, n) {
            cin >> c;
            mp[c] = i;
        }
        scanf("%d", &m);
        memset(g, 0, sizeof g);
        rep(i, 1, m){
            cin >> c1 >> r >> c2;
            g[mp[c1]][mp[c2]] = r;
         //    cout << c1 << ' ' <<r << ' '<< c2 <<endl;
        }

        printf("Case %d: ", ++t);
        printf(solve()?"Yes\n":"No\n");
    }

    return 0;
}

J - Invitation Cards

 POJ - 1511

In the age of television, not many people attend theater performances. Antique Comedians of Malidinesia are aware of this fact. They want to propagate theater and, most of all, Antique Comedies. They have printed invitation cards with all the necessary information and with the programme. A lot of students were hired to distribute these invitations among the people. Each student volunteer has assigned exactly one bus stop and he or she stays there the whole day and gives invitation to people travelling by bus. A special course was taken where students learned how to influence people and what is the difference between influencing and robbery. 

The transport system is very special: all lines are unidirectional and connect exactly two stops. Buses leave the originating stop with passangers each half an hour. After reaching the destination stop they return empty to the originating stop, where they wait until the next full half an hour, e.g. X:00 or X:30, where 'X' denotes the hour. The fee for transport between two stops is given by special tables and is payable on the spot. The lines are planned in such a way, that each round trip (i.e. a journey starting and finishing at the same stop) passes through a Central Checkpoint Stop (CCS) where each passenger has to pass a thorough check including body scan. 

All the ACM student members leave the CCS each morning. Each volunteer is to move to one predetermined stop to invite passengers. There are as many volunteers as stops. At the end of the day, all students travel back to CCS. You are to write a computer program that helps ACM to minimize the amount of money to pay every day for the transport of their employees. 

Input

The input consists of N cases. The first line of the input contains only positive integer N. Then follow the cases. Each case begins with a line containing exactly two integers P and Q, 1 <= P,Q <= 1000000. P is the number of stops including CCS and Q the number of bus lines. Then there are Q lines, each describing one bus line. Each of the lines contains exactly three numbers - the originating stop, the destination stop and the price. The CCS is designated by number 1. Prices are positive integers the sum of which is smaller than 1000000000. You can also assume it is always possible to get from any stop to any other stop.

Output

For each case, print one line containing the minimum amount of money to be paid each day by ACM for the travel costs of its volunteers.

Sample Input

2
2 2
1 2 13
2 1 33
4 6
1 2 10
2 1 60
1 3 20
3 4 10
2 4 5
4 1 50

Sample Output

46
210

和上面某题目一样,反过来建图就好了。

#include <cstdio>
#include <cstring>
#include <utility>
#include <iostream>
#include <map>
#include <queue>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
using namespace std;
typedef pair<long long, int> P;
typedef long long ll;
#define N 1000010
#define M 3645
const int INF = 0x3f3f3f3f;
const double eps = 1e-5;
const double PI = acos(-1);
#define fi first
#define se second
#define rep(i, lll, nnn) for(int i = (lll); i <= (nnn); i++)

int t, n, m, a[N], b[N], c[N];
struct Edge{
  int v, w, nex;
}edge[N];
int tot, fir[N];
void init()
{
    tot = 0;
    memset(fir, -1, sizeof fir);
}
void add(int u, int v, int w)
{
    edge[tot].v = v;
    edge[tot].w = w;
    edge[tot].nex = fir[u];
    fir[u] = tot++;
}
ll d[N], ans;
int que[N * 3];
bool vis[N];
//
//void spfa()
//{
//    int head = 0, tail = 0;
//    memset(d, INF, sizeof d);
//    memset(vis, false, sizeof vis);
//    d[1] = 0;
//    vis[1] = true;
//    que[tail++] = 1;
//
//    while(head < tail) {
//        int v = que[head++];
//        vis[v] = false;
//        for(int i = fir[v]; i != -1; i = edge[i].nex) {
//            if(d[edge[i].v] > d[v] + edge[i].w) {
//                d[edge[i].v] = d[v] + edge[i].w;
//                if(!vis[edge[i].v]) {
//                    vis[edge[i].v] = true;
//                    que[tail++] = edge[i].v;
//                }
//            }
//        }
//    }
//}


void spfa()
{
    int l = 0;
    memset(d, INF, sizeof d);
    memset(vis, false, sizeof vis);
    d[1] = 0;
    vis[1] = true;
    que[l++] = 1;

    while(l) {
        int v = que[--l];
        vis[v] = false;
        for(int i = fir[v]; i != -1; i = edge[i].nex) {
            if(d[edge[i].v] > d[v] + edge[i].w) {
                d[edge[i].v] = d[v] + edge[i].w;
                if(!vis[edge[i].v]) {
                    vis[edge[i].v] = true;
                    que[l++] = edge[i].v;
                }
            }
        }
    }
}


int main()
{
    #ifndef ONLINE_JUDGE
    freopen("data.txt", "r", stdin);
    #endif

    scanf("%d", &t);
    while(t--) {
        scanf("%d%d", &n, &m);
        init();
        rep(i, 1, m) {
            scanf("%d%d%d", &a[i], &b[i], &c[i]);
            add(a[i], b[i], c[i]);
        }
        spfa();
        ans = 0;
        rep(i, 2, n) ans += d[i];
        init();
        rep(i, 1, m) add(b[i], a[i], c[i]);
        spfa();
        rep(i, 2, n) ans += d[i];
        printf("%lld\n", ans);
    }

    return 0;
}

K - Candies

 POJ - 3159 

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 AB and cin 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.

emmmmmmmmm在北大做过,是差分约束的题。不是很能理解spfa+stack和spfa+queue的区别。这俩应该有各自适合的图,百度也没百度到什么,有说stack判负环快,其他的我猜大概细细长长的适合栈吧。。。。。怎么这题就只能用stack呢。

#include <cstdio>
#include <cstring>
#include <utility>
#include <iostream>
#include <map>
#include <queue>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
using namespace std;
typedef pair<long long, int> P;
typedef long long ll;
#define N 30010
#define M 150010
const int INF = 0x3f3f3f3f;
const double eps = 1e-5;
const double PI = acos(-1);
#define fi first
#define se second
#define rep(i, lll, nnn) for(int i = (lll); i <= (nnn); i++)

int t, n, m, a, b, c;
struct Edge{
  int v, w, nex;
}edge[M];
int tot, fir[N];
void init()
{
    tot = 0;
    memset(fir, -1, sizeof fir);
}
void add(int u, int v, int w)
{
    edge[tot].v = v;
    edge[tot].w = w;
    edge[tot].nex = fir[u];
    fir[u] = tot++;
}
ll d[N], ans;
int que[10000000];
bool vis[N];

void spfa()
{
    int l = 0;
    memset(d, INF, sizeof d);
    memset(vis, false, sizeof vis);
    d[1] = 0;
    vis[1] = true;
    que[l++] = 1;

    while(l) {
        int v = que[--l];
        vis[v] = false;
        for(int i = fir[v]; i != -1; i = edge[i].nex) {
            if(d[edge[i].v] > d[v] + edge[i].w) {
                d[edge[i].v] = d[v] + edge[i].w;
                if(!vis[edge[i].v]) {
                    vis[edge[i].v] = true;
                    que[l++] = edge[i].v;
                }
            }
        }
    }
}

//void spfa()
//{
//    int head = 0, tail = 0;
//    memset(d, INF, sizeof d);
//    memset(vis, false, sizeof vis);
//    d[1] = 0;
//    vis[1] = true;
//    que[tail++] = 1;
//
//    while(head != tail) {
//        int v = que[head++];
//        if(head >= 1000000) head = 0;
//        vis[v] = false;
//        for(int i = fir[v]; i != -1; i = edge[i].nex) {
//            if(d[edge[i].v] > d[v] + edge[i].w) {
//                d[edge[i].v] = d[v] + edge[i].w;
//                if(!vis[edge[i].v]) {
//                    vis[edge[i].v] = true;
//                    que[tail++] = edge[i].v;
//                    if(tail >= 1000000) tail = 0;
//                }
//            }
//        }
//    }
//}

int main()
{
    #ifndef ONLINE_JUDGE
    freopen("data.txt", "r", stdin);
    #endif

    while(~scanf("%d%d", &n, &m)) {
        init();
        rep(i, 1, m) {
            scanf("%d%d%d", &a, &b, &c);
            add(a, b, c);
        }
        spfa();
        printf("%lld\n", d[n]);
    }

    return 0;
}

L - Subway

 POJ - 2502

You have just moved from a quiet Waterloo neighbourhood to a big, noisy city. Instead of getting to ride your bike to school every day, you now get to walk and take the subway. Because you don't want to be late for class, you want to know how long it will take you to get to school. 
You walk at a speed of 10 km/h. The subway travels at 40 km/h. Assume that you are lucky, and whenever you arrive at a subway station, a train is there that you can board immediately. You may get on and off the subway any number of times, and you may switch between different subway lines if you wish. All subway lines go in both directions.

Input

Input consists of the x,y coordinates of your home and your school, followed by specifications of several subway lines. Each subway line consists of the non-negative integer x,y coordinates of each stop on the line, in order. You may assume the subway runs in a straight line between adjacent stops, and the coordinates represent an integral number of metres. Each line has at least two stops. The end of each subway line is followed by the dummy coordinate pair -1,-1. In total there are at most 200 subway stops in the city.

Output

Output is the number of minutes it will take you to get to school, rounded to the nearest minute, taking the fastest route.

Sample Input

0 0 10000 1000
0 200 5000 200 7000 200 -1 -1 
2000 600 5000 600 10000 600 -1 -1

Sample Output

21

这一题难在建图上——同一条线上相邻的车站连接,然后所有点之间建立人走的路。

#include <cstdio>
#include <cstring>
#include <utility>
#include <iostream>
#include <map>
#include <queue>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
using namespace std;
typedef pair<long long, int> P;
typedef long long ll;
#define N 210
#define M 150010
const double INF = 1e30;
const double eps = 1e-5;
const double PI = acos(-1);
#define fi first
#define se second
#define rep(i, lll, nnn) for(int i = (lll); i <= (nnn); i++)

double cost[N + 1][N + 1];
struct Node {
  double x, y;
}node[N];
double getd(Node a, Node b){
    return sqrt((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y));
}
double d[N];
bool vis[N];

void dijkstra(int n, int s)
{
    rep(i, 1, n) {
        d[i] = INF;
        vis[i] = false;
    }

    d[s] = 0;
    rep(k, 1, n) {
        int p = -1;
        double minc = INF;
        rep(i, 1, n) if(!vis[i] && d[i] < minc) {
            minc = d[i]; p = i;
        }
        if(p == -1) break;
        vis[p] = true;
        rep(i, 1, n) {
            if(!vis[i] && d[p] + cost[p][i] < d[i]) {
                d[i] = d[p] + cost[p][i];
            }
        }
    }
}
void init()
{
    rep(i, 1, N) rep(j, 1, N)
        cost[i][j] = (i == j?0.0:INF);
}

int main()
{
    #ifndef ONLINE_JUDGE
    freopen("data.txt", "r", stdin);
    #endif

    const double v1 = 10000.0 / 60, v2 = 40000.0 / 60;
    while(~scanf("%lf%lf%lf%lf", &node[1].x, &node[1].y, &node[2].x, &node[2].y)) {
        int n = 2, cnt = 3, x, y;
        init();
        while(~scanf("%d%d", &x, &y)) {
            if(x == -1 && y == -1) {
                cnt = n + 1; continue;
            }
            n++;
            node[n].x = x; node[n].y = y;
            if(n != cnt) {
                cost[n][n - 1] = cost[n - 1][n] = min(cost[n][n - 1], getd(node[n], node[n - 1]) / v2);
            }
            //cout << cost[n][n - 1] <<endl;
        }
 //rep(i, 1, n)rep(j, 1, n) cout << cost[i][j] <<endl;

        rep(i, 1, n) rep(j, 1, n)
            cost[i][j] = min(cost[i][j], getd(node[i], node[j]) / v1);


        dijkstra(n, 1);
        printf("%.0f\n", d[2]);
    }

    return 0;
}

M - 昂贵的聘礼

 POJ - 1062

年轻的探险家来到了一个印第安部落里。在那里他和酋长的女儿相爱了,于是便向酋长去求亲。酋长要他用10000个金币作为聘礼才答应把女儿嫁给他。探险家拿不出这么多金币,便请求酋长降低要求。酋长说:"嗯,如果你能够替我弄到大祭司的皮袄,我可以只要8000金币。如果你能够弄来他的水晶球,那么只要5000金币就行了。"探险家就跑到大祭司那里,向他要求皮袄或水晶球,大祭司要他用金币来换,或者替他弄来其他的东西,他可以降低价格。探险家于是又跑到其他地方,其他人也提出了类似的要求,或者直接用金币换,或者找到其他东西就可以降低价格。不过探险家没必要用多样东西去换一样东西,因为不会得到更低的价格。探险家现在很需要你的帮忙,让他用最少的金币娶到自己的心上人。另外他要告诉你的是,在这个部落里,等级观念十分森严。地位差距超过一定限制的两个人之间不会进行任何形式的直接接触,包括交易。他是一个外来人,所以可以不受这些限制。但是如果他和某个地位较低的人进行了交易,地位较高的的人不会再和他交易,他们认为这样等于是间接接触,反过来也一样。因此你需要在考虑所有的情况以后给他提供一个最好的方案。 
为了方便起见,我们把所有的物品从1开始进行编号,酋长的允诺也看作一个物品,并且编号总是1。每个物品都有对应的价格P,主人的地位等级L,以及一系列的替代品Ti和该替代品所对应的"优惠"Vi。如果两人地位等级差距超过了M,就不能"间接交易"。你必须根据这些数据来计算出探险家最少需要多少金币才能娶到酋长的女儿。 

Input

输入第一行是两个整数M,N(1 <= N <= 100),依次表示地位等级差距限制和物品的总数。接下来按照编号从小到大依次给出了N个物品的描述。每个物品的描述开头是三个非负整数P、L、X(X < N),依次表示该物品的价格、主人的地位等级和替代品总数。接下来X行每行包括两个整数T和V,分别表示替代品的编号和"优惠价格"。

Output

输出最少需要的金币数。

Sample Input

1 4
10000 3 2
2 8000
3 5000
1000 2 1
4 200
3000 2 1
4 200
50 2 0

Sample Output

5250

本来我天真的以为点ab只要不和起始点相差超过m并且ab之间不超过m就能建边,不过这样就会出现矛盾的情况(比源点大和比源点小的之间就可能gg)。解法是枚举一个长度为m的等级区间。源点的等级在区间里。

#include <cstdio>
#include <cstring>
#include <utility>
#include <iostream>
#include <map>
#include <queue>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
using namespace std;
typedef pair<long long, int> P;
typedef long long ll;
#define N 110
#define M 150010
const int INF = 0x3f3f3f3f;
const double eps = 1e-5;
const double PI = acos(-1);
#define fi first
#define se second
#define rep(i, lll, nnn) for(int i = (lll); i <= (nnn); i++)

int n, m;
int g[N][N];
struct Node {
  int p, l, x;
  vector<P> vct;
}node[N];
int d[N], ans;
bool vis[N];

void dijkstra()
{
    memset(d, INF, sizeof d);
    memset(vis, false, sizeof vis);
    d[1] = 0;
    rep(k, 1, n) {
        int p = -1;
        int minc = INF;
        rep(i, 1, n) if(!vis[i] && d[i] < minc) {
            minc = d[i]; p = i;
        }
        if(p == -1) break;
        vis[p] = true;
        rep(i, 1, n) {
            if(!vis[i] && d[p] + g[p][i] < d[i]) {
                d[i] = d[p] + g[p][i];
            }
        }
    }
}

int main()
{
    #ifndef ONLINE_JUDGE
    freopen("data.txt", "r", stdin);
    #endif

    scanf("%d%d", &m, &n);
    n++;
    rep(i, 2, n) {
        scanf("%d%d%d", &node[i].p, &node[i].l, &node[i].x);
        rep(j, 1, node[i].x) {
            int t, v;
            scanf("%d%d", &t, &v);
            node[i].vct.push_back(P(t + 1, v));
        }
    }

    ans = INF;
    for(int k = max(0, node[2].l - m); k <= node[2].l; k++) {
        memset(g, INF, sizeof g);
        rep(i, 1, n) g[i][i] = 0;
        int L = k, R = k + m;
        rep(i, 2, n) g[1][i] = node[i].p;
        rep(i, 2, n) {
            rep(j, 0, node[i].x - 1) {
                if(node[i].l < L || node[i].l > R) continue;
                P h = node[i].vct[j];
                int t = h.fi, v = h.se;
                if(node[t].l >= L && node[t].l <= R) {
                     g[t][i] = v;
                }
            }
        }
        dijkstra();
        ans = min(ans, d[2]);
    }

    printf("%d\n", ans);

    return 0;
}


N - Tram

 POJ - 1847

Tram network in Zagreb consists of a number of intersections and rails connecting some of them. In every intersection there is a switch pointing to the one of the rails going out of the intersection. When the tram enters the intersection it can leave only in the direction the switch is pointing. If the driver wants to go some other way, he/she has to manually change the switch. 

When a driver has do drive from intersection A to the intersection B he/she tries to choose the route that will minimize the number of times he/she will have to change the switches manually. 

Write a program that will calculate the minimal number of switch changes necessary to travel from intersection A to intersection B. 

Input

The first line of the input contains integers N, A and B, separated by a single blank character, 2 <= N <= 100, 1 <= A, B <= N, N is the number of intersections in the network, and intersections are numbered from 1 to N. 

Each of the following N lines contain a sequence of integers separated by a single blank character. First number in the i-th line, Ki (0 <= Ki <= N-1), represents the number of rails going out of the i-th intersection. Next Ki numbers represents the intersections directly connected to the i-th intersection.Switch in the i-th intersection is initially pointing in the direction of the first intersection listed. 

Output

The first and only line of the output should contain the target minimal number. If there is no route from A to B the line should contain the integer "-1".

Sample Input

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

Sample Output

0

建图是除了第一个为0其他的值都为1.

#include <cstdio>
#include <cstring>
#include <utility>
#include <iostream>
#include <map>
#include <queue>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
using namespace std;
typedef pair<long long, int> P;
typedef long long ll;
#define N 110
#define M 150010
const int INF = 0x3f3f3f3f;
const double eps = 1e-5;
const double PI = acos(-1);
#define fi first
#define se second
#define rep(i, lll, nnn) for(int i = (lll); i <= (nnn); i++)

int n, a, b, num, c;
int g[N][N];
int d[N], ans;
bool vis[N];

void dijkstra()
{
    memset(d, INF, sizeof d);
    memset(vis, false, sizeof vis);
    d[a] = 0;

    rep(k, 1, n) {
        int p = -1;
        int minc = INF;
        rep(i, 1, n) if(!vis[i] && d[i] < minc) {
            minc = d[i]; p = i;
        }

        if(p == -1) break;
        vis[p] = true;
        rep(i, 1, n) {
            if(!vis[i] && d[p] + g[p][i] < d[i]) {
                d[i] = d[p] + g[p][i];
            }
        }
    }
}

int main()
{
    #ifndef ONLINE_JUDGE
    freopen("data.txt", "r", stdin);
    #endif

    memset(g, INF, sizeof g);
    rep(i, 1, N - 1) g[i][i] = 0;
    scanf("%d%d%d", &n, &a, &b);
    rep(i, 1, n) {
        scanf("%d", &num);
        if(num > 0) scanf("%d", &c);
        else continue;
        g[i][c] = 0;
        rep(j, 2, num) {
            scanf("%d", &c);
            g[i][c] = 1;
        }
    }
//    rep(i, 1, n) rep(j, 1, n)
//        cout << i <<' ' <<j <<' ' <<g[i][j] <<endl;
    dijkstra();

    if(d[b] == INF) d[b] = -1;
    printf("%d\n", d[b]);

    return 0;
}


O - Extended Traffic

 LightOJ - 1074

Dhaka city is getting crowded and noisy day by day. Certain roads always remain blocked in congestion. In order to convince people avoid shortest routes, and hence the crowded roads, to reach destination, the city authority has made a new plan. Each junction of the city is marked with a positive integer (≤ 20) denoting the busyness of the junction. Whenever someone goes from one junction (the source junction) to another (the destination junction), the city authority gets the amount (busyness of destination - busyness of source)3 (that means the cube of the difference) from the traveler. The authority has appointed you to find out the minimum total amount that can be earned when someone intelligent goes from a certain junction (the zero point) to several others.

Input

Input starts with an integer T (≤ 50), denoting the number of test cases.

Each case contains a blank line and an integer n (1 < n ≤ 200) denoting the number of junctions. The next line contains nintegers denoting the busyness of the junctions from 1 to n respectively. The next line contains an integer m, the number of roads in the city. Each of the next m lines (one for each road) contains two junction-numbers (source, destination) that the corresponding road connects (all roads are unidirectional). The next line contains the integer q, the number of queries. The next q lines each contain a destination junction-number. There can be at most one direct road from a junction to another junction.

Output

For each case, print the case number in a single line. Then print q lines, one for each query, each containing the minimum total earning when one travels from junction 1 (the zero point) to the given junction. However, for the queries that gives total earning less than 3, or if the destination is not reachable from the zero point, then print a '?'.

Sample Input

2

 

5

6 7 8 9 10

6

1 2

2 3

3 4

1 5

5 4

4 5

2

4

5

 

2

10 10

1

1 2

1

2

Sample Output

Case 1:

3

4

Case 2:

?

本来就不会用spfa判断负环,要判断一个点是否连着这个负环就更不会了,要靠深搜。

#include <cstdio>
#include <cstring>
#include <utility>
#include <iostream>
#include <map>
#include <queue>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
using namespace std;
typedef pair<long long, int> P;
typedef long long ll;
#define N 210
#define M 15010
const int INF = 0x3f3f3f3f;
const double eps = 1e-5;
const double PI = acos(-1);
#define fi first
#define se second
#define rep(i, lll, nnn) for(int i = (lll); i <= (nnn); i++)

int n, m, a, b, w[N], q, c;
int d[N], ans;
bool vis[N];

struct Edge {
  int v, w, nex;
}edge[M];
int tot, fir[N], que[2000000], cnt[N];
bool cir[N];

void init()
{
    tot = 0;
    memset(fir, -1, sizeof fir);
}

void add(int u, int v, int w)
{
    edge[tot].v = v;
    edge[tot].w = w;
    edge[tot].nex = fir[u];
    fir[u] = tot++;
}

void dfs(int s)
{
    cir[s] = true;
    for(int i = fir[s]; i != -1; i = edge[i].nex) {
        if(!cir[edge[i].v]) dfs(edge[i].v);
    }
}

void spfa()
{
    int head = 0, tail = 0;
    memset(d, INF, sizeof d);
    memset(cnt, 0, sizeof cnt);
    memset(vis, false, sizeof vis);
    memset(cir, false, sizeof cir);
    que[tail++] = 1;
    vis[1] = true;
    d[1] = 0;

    while(head < tail) {
        int h = que[head++];
        vis[h] = false;

        for(int i = fir[h]; i != -1; i = edge[i].nex) {
            if(!cir[edge[i].v] && d[edge[i].v] > d[h] + edge[i].w) {
                d[edge[i].v] = d[h] + edge[i].w;

                if(!vis[edge[i].v]) {
                    que[tail++] = edge[i].v;
                    vis[edge[i].v] = true;

                    cnt[edge[i].v]++;
                    if(cnt[edge[i].v] > n) {
                        dfs(edge[i].v);
                    }
                }
            }
        }
    }
}

int main()
{
    #ifndef ONLINE_JUDGE
    freopen("data.txt", "r", stdin);
    #endif

    int t;
    scanf("%d", &t);
    rep(Case, 1, t) {
        scanf("%d", &n);
        rep(i, 1, n) scanf("%d", &w[i]);
        scanf("%d", &m);
        init();
        rep(i, 1, m) {
            scanf("%d%d", &a, &b);
            add(a, b, (w[b]-w[a])*(w[a]-w[b])*(w[a]-w[b]));
        }
        spfa();
        scanf("%d", &q);
        printf("Case %d:\n", Case);
        while(q--) {
            scanf("%d", &c);
            if(d[c] == INF || d[c] < 3 || cir[c]) printf("?\n");
            else printf("%d\n", d[c]);
        }
    }

    return 0;
}

P - The Shortest Path in Nya Graph

 HDU - 4725

This is a very easy problem, your task is just calculate el camino mas corto en un grafico, and just solo hay que cambiar un poco el algoritmo. If you do not understand a word of this paragraph, just move on. 
The Nya graph is an undirected graph with "layers". Each node in the graph belongs to a layer, there are N nodes in total. 
You can move from any node in layer x to any node in layer x + 1, with cost C, since the roads are bi-directional, moving from layer x + 1 to layer x is also allowed with the same cost. 
Besides, there are M extra edges, each connecting a pair of node u and v, with cost w. 
Help us calculate the shortest path from node 1 to node N.

Input

The first line has a number T (T <= 20) , indicating the number of test cases. 
For each test case, first line has three numbers N, M (0 <= N, M <= 10 5) and C(1 <= C <= 10 3), which is the number of nodes, the number of extra edges and cost of moving between adjacent layers. 
The second line has N numbers l i (1 <= l i <= N), which is the layer of i th node belong to. 
Then come N lines each with 3 numbers, u, v (1 <= u, v < =N, u <> v) and w (1 <= w <= 10 4), which means there is an extra edge, connecting a pair of node u and v, with cost w.

Output

For test case X, output "Case #X: " first, then output the minimum cost moving from node 1 to node N. 
If there are no solutions, output -1.

Sample Input

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

3 3 3
1 3 2
1 2 2
2 3 2
1 3 4

Sample Output

Case #1: 2
Case #2: 3

这题的朴素建图(n^2)会超时,方法是把层抽象成点,点到相邻层只需要链接该点到相邻层抽象出的点,而不需要把该点一一和相邻所有点相连。然后每层要和自己的层所在的相连,边赋值为0.

#include <cstdio>
#include <cstring>
#include <utility>
#include <iostream>
#include <map>
#include <queue>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
using namespace std;
typedef pair<long long, int> P;
typedef long long ll;
#define N 100010
#define M 1500100
const int INF = 0x3f3f3f3f;
const double eps = 1e-5;
const double PI = acos(-1);
#define fi first
#define se second
#define rep(i, lll, nnn) for(int i = (lll); i <= (nnn); i++)

int t, n, m, a, b, c, u, v, w;
//vector<int> layer[N];
struct Edge{
  int v, w, nex;
}edge[M];
int tot, fir[M];
void init()
{
    tot = 0;
    memset(fir, -1, sizeof fir);
}
void add(int u, int v, int w)
{
    edge[tot].v = v;
    edge[tot].w = w;
    edge[tot].nex = fir[u];
    fir[u] = tot++;
}
int d[N * 2];
bool vis[N * 2];
queue<int> que;

void spfa()
{
    while(!que.empty()) que.pop();
    memset(d, INF, sizeof d);
    memset(vis, false, sizeof vis);
    d[1] = 0;
    vis[1] = true;
    que.push(1);

    while(!que.empty()) {
        int v = que.front(); que.pop();
        vis[v] = false;
        for(int i = fir[v]; i != -1; i = edge[i].nex) {
            if(d[edge[i].v] > d[v] + edge[i].w) {
                d[edge[i].v] = d[v] + edge[i].w;
                if(!vis[edge[i].v]) {
                    vis[edge[i].v] = true;
                    que.push(edge[i].v);
                }
            }
        }
    }
}


int main()
{
    #ifndef ONLINE_JUDGE
    freopen("data.txt", "r", stdin);
    #endif

    scanf("%d", &t);

    rep(Case, 1, t) {
        scanf("%d%d%d", &n, &m, &c);

        init();
        rep(i, 1, n) {
            scanf("%d", &a);
            add(a + n, i, 0);
            if(a > 1) add(i, a + n - 1, c);
            if(a < n) add(i, a + n + 1, c);
        }
        rep(i, 1, m) {
            scanf("%d%d%d", &u, &v, &w);
            add(u, v, w);
            add(v, u, w);
        }
        spfa();
        if(d[n] == INF) d[n] = -1;
        printf("Case #%d: %d\n", Case, d[n]);
    }

    return 0;
}


Q - Marriage Match IV

 HDU - 3416 

Do not sincere non-interference。 
Like that show, now starvae also take part in a show, but it take place between city A and B. Starvae is in city A and girls are in city B. Every time starvae can get to city B and make a data with a girl he likes. But there are two problems with it, one is starvae must get to B within least time, it's said that he must take a shortest path. Other is no road can be taken more than once. While the city starvae passed away can been taken more than once. 


So, under a good RP, starvae may have many chances to get to city B. But he don't know how many chances at most he can make a data with the girl he likes . Could you help starvae?

Input

The first line is an integer T indicating the case number.(1<=T<=65) 
For each case,there are two integer n and m in the first line ( 2<=n<=1000, 0<=m<=100000 ) ,n is the number of the city and m is the number of the roads. 

Then follows m line ,each line have three integers a,b,c,(1<=a,b<=n,0<c<=1000)it means there is a road from a to b and it's distance is c, while there may have no road from b to a. There may have a road from a to a,but you can ignore it. If there are two roads from a to b, they are different. 

At last is a line with two integer A and B(1<=A,B<=N,A!=B), means the number of city A and city B. 
There may be some blank line between each case.

Output

Output a line with a integer, means the chances starvae can get at most.

Sample Input

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

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

2 2
1 2 1
1 2 2
1 2

Sample Output

2
1
1

要求出路有多少条,且每条路只能走一次,这就变成网络流了Orz。先把组成最短路的弧找出来(正反向建图找到d1和d2,然后一波操作对每个弧ab能minpath = Wab + d[a] + d[b]的就丢进网络流里去),再在这些弧上跑网络流Orz。

抄了个Kuangbin自己的博客代码,看不懂SAP啊啊啊啊啊啊啊啊啊啊啊啊Orz。

#include <cstdio>
#include <cstring>
#include <utility>
#include <iostream>
#include <map>
#include <queue>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
using namespace std;
typedef pair<long long, int> P;
typedef long long ll;
#define N 2010
#define M 2000100
const int INF = 0x3f3f3f3f;
const double eps = 1e-5;
const double PI = acos(-1);
#define fi first
#define se second
#define rep(i, lll, nnn) for(int i = (lll); i <= (nnn); i++)

//SAP
struct Node {
  int to, nxt, cap;
}edge[M];
int tot, head[N];
int gap[N], dis[N], pre[N], cur[N];
void init()
{
    tot = 0;
    memset(head, -1, sizeof head);
}
void addedge(int u, int v, int w, int rw = 0)
{
    edge[tot].to = v; edge[tot].cap = w;
    edge[tot].nxt = head[u]; head[u] = tot++;
    edge[tot].to = u; edge[tot].cap = rw;
    edge[tot].nxt = head[v]; head[v] = tot++;
}

int sap(int start, int end, int nodenum)
{
    memset(dis, 0, sizeof dis);
    memset(gap, 0, sizeof gap);
    memcpy(cur, head, sizeof head);
    int u = pre[start] = start, maxflow = 0, aug = -1;
    gap[0] = nodenum;
    while(dis[start] < nodenum) {
        loop:
            for(int & i = cur[u]; ~i; i = edge[i].nxt) {
                int v = edge[i].to;
                if(edge[i].cap && dis[u] == dis[v] + 1) {
                    if(aug == -1 || aug > edge[i].cap)
                        aug = edge[i].cap;
                    pre[v] = u;
                    u = v;
                    if(v == end) {
                        maxflow += aug;
                        for(u = pre[u]; v != start; v = u, u = pre[u]) {
                            edge[cur[u]].cap -= aug;
                            edge[cur[u]^1].cap += aug;
                        }
                        aug = -1;
                    }
                    goto loop;
                }
            }
            int mindis = nodenum;
            for(int i = head[u]; ~i; i = edge[i].nxt) {
                int v = edge[i].to;
                if(edge[i].cap && mindis > dis[v]) {
                    cur[u] = i;
                    mindis = dis[v];
                }
            }
            if((--gap[dis[u]]) == 0) break;
            gap[dis[u] = mindis + 1]++;
            u = pre[u];
    }
    return maxflow;
}

//SPFA
int first[N];
bool vis[N];
int cnt[N];
int que[N];
int dist[N];
struct Edge {
  int to, v, nxt;
}edgel[M];
int tt;
void add(int a, int b, int v)
{
    edgel[tt].to = b;
    edgel[tt].v = v;
    edgel[tt].nxt = first[a];
    first[a] = tt++;
}
bool spfa(int start, int n)
{
    int front = 0, rear = 0;
    for(int v = 1; v <= n; v++) {
        if(v == start) {
            que[rear++] = v;
            vis[v] = true;
            cnt[v] = 1;
            dist[v] = 0;
        }
        else {
            vis[v] = false;
            cnt[v] = 0;
            dist[v] = INF;
        }
    }

    while(front < rear) {
        int u = que[front++];
        vis[u] = false;
        if(front >= N) front = 0;
        for(int i = first[u]; ~i; i = edgel[i].nxt) {
            int v = edgel[i].to;
            if(dist[v] > dist[u] + edgel[i].v) {
                dist[v] = dist[u] + edgel[i].v;
                if(!vis[v]) {
                    vis[v] = true;
                    que[rear++] = v;
                    if(rear >= N) rear = 0;
                    if(++cnt[v] > n) return false;
                }
            }
        }
    }
    return false;
}
int a[100010], b[100010], c[100010];
int d1[N], d2[N];

int main()
{
    #ifndef ONLINE_JUDGE
    freopen("data.txt", "r", stdin);
    #endif

    int t, n, m;
    scanf("%d", &t);

    while(t--) {
        scanf("%d%d", &n, &m);
        int A, B;
        rep(i, 0, m - 1) {
            scanf("%d%d%d", &a[i], &b[i], &c[i]);
        }
        scanf("%d%d", &A, &B);

        tt = 0;
        memset(first, -1, sizeof first);
        for(int i = 0; i < m; i++)
            add(a[i], b[i], c[i]);
        spfa(A, n);
        memcpy(d1, dist, sizeof dist);
//cout << "aa " <<dist[B] <<endl;
        tt = 0;
        memset(first, -1, sizeof first);
        for(int i = 0; i < m; i++)
            add(b[i], a[i], c[i]);
        spfa(B, n);
        memcpy(d2, dist, sizeof dist);
//cout <<"bb "<<dist[A] <<endl;
        init();
        for(int i = 0; i < m; i++) {
            if(a[i] != b[i] && d1[a[i]] + d2[b[i]] + c[i] == d1[B])
                addedge(a[i], b[i], 1);
        }

        printf("%d\n", sap(A, B, n));
    }

    return 0;
}


R - 0 or 1

 HDU - 4370 

Given a n*n matrix C ij (1<=i,j<=n),We want to find a n*n matrix X ij(1<=i,j<=n),which is 0 or 1. 

Besides,X ij meets the following conditions: 

1.X 12+X 13+...X 1n=1 
2.X 1n+X 2n+...X n-1n=1 
3.for each i (1<i<n), satisfies ∑X ki (1<=k<=n)=∑X ij (1<=j<=n). 

For example, if n=4,we can get the following equality: 

X 12+X 13+X 14=1 
X 14+X 24+X 34=1 
X 12+X 22+X 32+X 42=X 21+X 22+X 23+X 24 
X 13+X 23+X 33+X 43=X 31+X 32+X 33+X 34 

Now ,we want to know the minimum of ∑C ij*X ij(1<=i,j<=n) you can get. 

Hint


For sample, X 12=X 24=1,all other X ij is 0. 

Input

The input consists of multiple test cases (less than 35 case). 
For each test case ,the first line contains one integer n (1<n<=300). 
The next n lines, for each lines, each of which contains n integers, illustrating the matrix C, The j-th integer on i-th line is C ij(0<=C ij<=100000).

Output

For each case, output the minimum of ∑C ij*X ij you can get. 

Sample Input

4
1 2 4 10
2 0 1 1
2 2 0 5
6 3 1 2

Sample Output

3

这题TMD是最短路????????一般题目都是建图建邻接矩阵,这题是给你矩阵你来猜图。。。Orz。X矩阵为1的Xij一定就是点ij相连了,但是什么样的图能让 ∑C ij*X ij(1<=i,j<=n). 最小呢?是最短路的图(由第一和第二个限制条件知道节点1出度为1和节点n的入度为1,由条件三知道其他点出度等于入度,即其他点度数是偶数,又因为握手定理所有点度数和为偶数所以有两个可能——1.节点1连着节点n。2.节点1和节点n都处于环中,俩的度数自身就是偶数),最短路的图适合第一种可能,第二种要求最小环。求最小环也是门学问,例如求1的最小环,不能从1开始松弛,而是要先人工完成第一步松弛操作把和1连接的点先加进队列,并令d[1]为INF以便于1连接的点来松弛1,如果从1开始松弛d[1]会被初始化为0,gg。

#include <cstdio>
#include <cstring>
#include <utility>
#include <iostream>
#include <map>
#include <queue>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
using namespace std;
typedef pair<long long, int> P;
typedef long long ll;
#define N 310
#define M 2000100
const int INF = 0x3f3f3f3f;
const double eps = 1e-5;
const double PI = acos(-1);
#define fi first
#define se second
#define rep(i, lll, nnn) for(int i = (lll); i <= (nnn); i++)

int g[N][N];
int n;
bool vis[N];
int d[N], que[M];

void spfa(int s)
{
    int head = 0, tail = 0;
    d[s] = INF;
    vis[s] = false;
    rep(i, 1, n) if(i != s)
        d[i] = g[s][i], vis[i] = true, que[tail++] = i;

    while(head != tail) {
        int v = que[head++];
        vis[v] = false;
        if(head >= M) head = 0;
        rep(i, 1, n) {
            if(d[i] > d[v] + g[v][i]) {
                d[i] = d[v] + g[v][i];
                if(!vis[i]) {
                    vis[i] = true;
                    que[tail++] = i;
                    if(tail >= M) tail = 0;
                }
            }
        }
    }
}

int main()
{
    #ifndef ONLINE_JUDGE
    freopen("data.txt", "r", stdin);
    #endif

    while(~scanf("%d", &n)) {
        rep(i, 1, n) rep(j, 1, n) scanf("%d", &g[i][j]);
        spfa(1);
        int mind = d[n];
        int a = d[1];
        spfa(n);
        int b = d[n];
        printf("%d\n", min(mind, a + b));
    }

    return 0;
}



S - Layout

 POJ - 3169

Like everyone else, cows like to stand close to their friends when queuing for feed. FJ has N (2 <= N <= 1,000) cows numbered 1..N standing along a straight line waiting for feed. The cows are standing in the same order as they are numbered, and since they can be rather pushy, it is possible that two or more cows can line up at exactly the same location (that is, if we think of each cow as being located at some coordinate on a number line, then it is possible for two or more cows to share the same coordinate). 

Some cows like each other and want to be within a certain distance of each other in line. Some really dislike each other and want to be separated by at least a certain distance. A list of ML (1 <= ML <= 10,000) constraints describes which cows like each other and the maximum distance by which they may be separated; a subsequent list of MD constraints (1 <= MD <= 10,000) tells which cows dislike each other and the minimum distance by which they must be separated. 

Your job is to compute, if possible, the maximum possible distance between cow 1 and cow N that satisfies the distance constraints.

Input

Line 1: Three space-separated integers: N, ML, and MD. 

Lines 2..ML+1: Each line contains three space-separated positive integers: A, B, and D, with 1 <= A < B <= N. Cows A and B must be at most D (1 <= D <= 1,000,000) apart.

Lines ML+2..ML+MD+1: Each line contains three space-separated positive integers: A, B, and D, with 1 <= A < B <= N. Cows A and B must be at least D (1 <= D <= 1,000,000) apart.

Output

Line 1: A single integer. If no line-up is possible, output -1. If cows 1 and N can be arbitrarily far apart, output -2. Otherwise output the greatest possible distance between cows 1 and N.

Sample Input

4 2 1
1 3 10
2 4 20
2 3 3

Sample Output

27

Hint

Explanation of the sample: 

There are 4 cows. Cows #1 and #3 must be no more than 10 units apart, cows #2 and #4 must be no more than 20 units apart, and cows #2 and #3 dislike each other and must be no fewer than 3 units apart. 

The best layout, in terms of coordinates on a number line, is to put cow #1 at 0, cow #2 at 7, cow #3 at 10, and cow #4 at 27.

差分约束原来差不多都能变成最短路,加负号也是很骚了,,学习于这里。

#include <cstdio>
#include <cstring>
#include <utility>
#include <iostream>
#include <map>
#include <queue>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
using namespace std;
typedef pair<long long, int> P;
typedef long long ll;
#define N 1010
#define M 2000100
const int INF = 0x3f3f3f3f;
const double eps = 1e-5;
const double PI = acos(-1);
#define fi first
#define se second
#define rep(i, lll, nnn) for(int i = (lll); i <= (nnn); i++)

int n, ml, md;
struct Edge {
  int v, w, nxt;
}edge[M];
int tot, fir[N];
void init()
{
    tot = 0;
    memset(fir, -1, sizeof fir);
}
void add(int u, int v, int w)
{
    edge[tot].v = v;
    edge[tot].w = w;
    edge[tot].nxt = fir[u];
    fir[u] = tot++;
}

int d[N], cnt[N], que[N];
bool vis[N];
bool spfa()
{
    memset(d, INF, sizeof d);
    memset(cnt, 0, sizeof cnt);
    memset(vis, false, sizeof vis);
    int head = 0, tail = 0;

    cnt[1] = 1;
    vis[1] = true;
    d[1] = 0;
    que[tail++] = 1;

    while(head != tail) {
        int u = que[head++];
        vis[u] = false;
        if(head >= N) head = 0;
        for(int i = fir[u]; ~i; i = edge[i].nxt) {
            int v = edge[i].v;//cout <<u << ' '<<v <<endl;
            if(d[v] > d[u] + edge[i].w) {
                d[v] = d[u] + edge[i].w;
                if(!vis[v]) {
                    vis[v] = true;
                    cnt[v]++;
                    if(cnt[v] > n) return false;
                    que[tail++] = v;
                    if(tail >= N) tail = 0;
                }
            }
        }
    }

    return true;
}

int main()
{
    #ifndef ONLINE_JUDGE
    freopen("data.txt", "r", stdin);
    #endif

    while(~scanf("%d%d%d", &n, &ml, &md)) {
        init();
        int u, v, w;
        rep(i, 1, ml) {
            scanf("%d%d%d", &u, &v, &w);
            add(u, v, w);
        }
        rep(i, 1, md) {
            scanf("%d%d%d", &u, &v, &w);
            add(v, u, -w);
        }
        if(spfa()) {
            if(d[n] == INF) printf("-2\n");
            else printf("%d\n", d[n]);
        }
        else printf("-1\n");
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40379678/article/details/81539175
今日推荐