hdu4360 spfa+拆点

题目要求必须按照L O V E 的顺序行走,且必须至少有一个完整的LOVE,说明可以经过同一个点多次

对每个点拆分为4个点,分别为从L,O,V,E到达。起始点看做是从E到达的

spfa时发现当前点距离相同,比较经过的边数,此时若边数更大,也要入队列!因为要更新后面的点经过的边数

trick 是点可以有自环,当N = 1时

1 4

1 1 1 L

1 1 1 O

1 1 1 V

1 1 1 E

还有就是数据可能会超int

敲了两遍,第一遍dijsktra怎么测都对,trick也都想到了,就是WA到死,第二遍初始化手贱4写成3。。。

附送好多组数据。。。都是自己编的

//#pragma comment(linker, "/STACK:102400000,102400000")
//HEAD
#include <cstdio>
#include <cstring>
#include <vector>
#include <iostream>
#include <algorithm>

#include <queue>
#include <string>
#include <set>
#include <stack>
#include <map>
#include <cmath>
#include <cstdlib>

using namespace std;
//LOOP
#define FE(i, a, b) for(int i = (a); i <= (b); ++i)
#define FED(i, b, a) for(int i = (b); i>= (a); --i)
#define REP(i, N) for(int i = 0; i < (N); ++i)
#define CLR(A,value) memset(A,value,sizeof(A))
//STL
#define PB push_back
//INPUT
#define RI(n) scanf("%d", &n)
#define RII(n, m) scanf("%d%d", &n, &m)
#define RIII(n, m, k) scanf("%d%d%d", &n, &m, &k)
#define RS(s) scanf("%s", s)
typedef long long LL;
const int MAXN = 1010;

#define FF(i, a, b) for(int i = (a); i < (b); ++i)
#define FD(i, b, a) for(int i = (b) - 1; i >= (a); --i)
#define CPY(a, b) memcpy(a, b, sizeof(a))
#define FC(it, c) for(__typeof((c).begin()) it = (c).begin(); it != (c).end(); it++)
#define EQ(a, b) (fabs((a) - (b)) <= 1e-10)
#define ALL(c) (c).begin(), (c).end()
#define SZ(V) (int)V.size()
#define RIV(n, m, k, p) scanf("%d%d%d%d", &n, &m, &k, &p)
#define RV(n, m, k, p, q) scanf("%d%d%d%d%d", &n, &m, &k, &p, &q)
#define WI(n) printf("%d\n", n)
#define WS(s) printf("%s\n", s)
#define sqr(x) x * x
typedef vector <int> VI;
typedef unsigned long long ULL;
const double eps = 1e-10;
const LL MOD = 1e9 + 7;

typedef long long LL;
using namespace std;

const int maxn = 3010;
const LL INF = 1e18;

struct Edge{
    int from, to, dis, let;
    Edge(int u, int v, int w, int let): from(u), to(v), dis(w), let(let) {}
};

struct Node{
    int u, let;
    Node(int d, int let): u(d), let(let) {}
};

int n, m;
LL d[maxn][5];
int num[maxn][5], inq[maxn][5];
VI G[maxn];
vector<Edge> edges;

void init(int nn)
{
    n = nn;
    edges.clear();
    FE(i, 0, n) G[i].clear();
}

void addEdge(int u, int v, int w, int let)
{
    edges.push_back(Edge(u, v, w, let));
    m = edges.size();
    G[u].push_back(m - 1);
}

void spfa()
{
    queue<Node> Q;
    Q.push(Node(1, 3));
    FE(i, 0, n) REP(j, 4) d[i][j] = INF;
    CLR(num, 0), CLR(inq, 0);
    d[1][3] = 0, inq[1][3] = 1;
    while (!Q.empty())
    {
        Node x = Q.front();  Q.pop();
        int u = x.u, let = x.let;
        inq[u][let] = 0;
        REP(i, G[u].size())
        {
            Edge& e = edges[G[u][i]];
            if (e.let != (let + 1) % 4) continue;
            if (d[e.to][e.let] > d[u][let] + e.dis || !d[e.to][e.let])
            {
                d[e.to][e.let] = d[u][let] + e.dis;
                num[e.to][e.let] = num[u][let] + 1;
//                printf("now:%d to:%d letter:%d num:%d   d:%d\n", u, e.to, e.let, num[e.to][e.let], d[e.to][e.let]);
                if (!inq[e.to][e.let])
                {
                    inq[e.to][e.let] = 1;
                    Q.push(Node(e.to, e.let));
                }
            }
            else if (d[e.to][e.let] == d[u][let] + e.dis && num[e.to][e.let] <= num[u][let])
            {
                num[e.to][e.let] =  num[u][let] + 1;
                if (!inq[e.to][e.let])
                {
                    inq[e.to][e.let] = 1;
                    Q.push(Node(e.to, e.let));
                }
            }
        }
    }
}

int main()
{
    int T, N, M;
    RI(T);
    FE(kase, 1, T)
    {
        int x, y, z, let;
        char s[20];
        RII(N, M);
        init(N);
        REP(i, M)
        {
            RIII(x, y, z);
            RS(s);
            if (s[0] == 'L')    let = 0;
            if (s[0] == 'O')    let = 1;
            if (s[0] == 'V')    let = 2;
            if (s[0] == 'E')    let = 3;
            addEdge(x, y, z, let);
            addEdge(y, x, z, let);
        }
        spfa();
        printf("Case %d: ", kase);
//        cout << d[N][3] << num[N][3] << endl;
        if (d[N][3] == INF || num[N][3] / 4 < 1)
        {
            printf("Binbin you disappoint Sangsang again, damn it!\n");
            continue;
        }
        printf("Cute Sangsang, Binbin will come with a donkey after travelling %I64d meters and finding %d LOVE strings at last.\n",
                d[N][3], num[N][3] / 4);
    }
    return 0;
}
/*
55
6 6
1 2  10 L
 2 3 20 O
2 4 30 O
3 5 30 V
4 5 10 V
5 6 10 E
4 4
1 2 1 L
2 1 1 O
1 3 1 V
3 4 1 E
4 4
1 2 1 L
2 3 1 O
3 4 1 V
4 1 1 E
1 0
2 1
1 2  1 E

2 8
1 1 2 L
1 1 1 O
1 1 1 V
1 1 1 E
1 2 3 L
2 1 1 O
1 2 1 V
2 1 1 E

12  12
1 5 5 L
5 6 5 O
6 7 5 V
7 12 5 E
1 2 1 L
2 3 1 O
3 4 1 V
4 8 1 E
8 9 1 L
9 10 1 O
10 11 1 V
11 12 13 E

23 24
1 5 5 L
5 6 5 O
6 7 5 V
7 12 5 E
1 2 1 L
2 3 1 O
3 4 1 V
4 8 1 E
8 9 1 L
9 10 1 O
10 11 1 V
11 12 13 E
12 13 1 L
13 14 1 O
14 15 1 V
15 16 1 E
16 17 1 L
17 18 1 O
18 19 1 V
19 23 13 E
12 20 5 L
20 21 5 O
21 22 5 V
22 23 5 E
*/

hdu4360 spfa+拆点

时间: 2024-10-06 03:06:20

hdu4360 spfa+拆点的相关文章

hdu4360 spfa+分割点

标题要求必须按照L O V E 行走为了,你必须至少有一个完整的LOVE.说明可以通过同一个点反复 对每一个点拆分为4个点.分别为从L,O,V,E到达. 起始点看做是从E到达的 spfa时发现当前点距离同样,比較经过的边数,此时若边数更大,也要入队列!由于要更新后面的点经过的边数 trick 是点能够有自环,当N = 1时 1 4 1 1 1 L 1 1 1 O 1 1 1 V 1 1 1 E 还有就是数据可能会超int 敲了两遍,第一遍dijsktra怎么測都对,trick也都想到了.就是WA

hdu4360 As long as Binbin loves Sangsang spfa变形

题意:给定n个点m条边的无向图,每次必须沿着LOVE走,到终点时必须是完整的LOVE,且至少走出一个LOVE,问这样情况下最短 路是多少,在一样短情况下最多的LOVE个数是多少.注意:有自环!(见底下的数据) 思路:其实本质就是个最短路,用spfa就好.注意自环的特殊处理,详见代码: /********************************************************* file name: hdu4360.cpp author : kereo create tim

Bzoj 2763: [JLOI2011]飞行路线 拆点,分层图,最短路,SPFA

2763: [JLOI2011]飞行路线 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1694  Solved: 635[Submit][Status][Discuss] Description Alice和Bob现在要乘飞机旅行,他们选择了一家相对便宜的航空公司.该航空公司一共在n个城市设有业务,设这些城市分别标记为0到n-1,一共有m种航线,每种航线连接两个城市,并且航线有一定的价格.Alice和Bob现在要从一个城市沿着航线到达另一个城市

Codevs1021题解---SPFA+路径记录

题目描述 Description 麦克找了个新女朋友,玛丽卡对他非常恼火并伺机报复. 因为她和他们不住在同一个城市,因此她开始准备她的长途旅行. 在这个国家中每两个城市之间最多只有一条路相通,并且我们知道从一个城市到另一个城市路上所需花费的时间. 麦克在车中无意中听到有一条路正在维修,并且那儿正堵车,但没听清楚到底是哪一条路.无论哪一条路正在维修,从玛丽卡所在的城市都能到达麦克所在的城市. 玛丽卡将只从不堵车的路上通过,并且她将按最短路线行车.麦克希望知道在最糟糕的情况下玛丽卡到达他所在的城市需

bzoj 2285 [Sdoi2011]保密(二分,spfa + 最大流)

Description 现在,保密成为一个很重要也很困难的问题.如果没有做好,后果是严重的.比如,有个人没有自己去修电脑,又没有拆硬盘,后来的事大家都知道了. 当然,对保密最需求的当然是军方,其次才是像那个人.为了应付现在天上飞来飞去的卫星,军事基地一般都会建造在地下. 某K国的军事基地是这样子的:地面上两排大天井共n1个作为出入口,内部是许多除可以共享出入口外互不连通的空腔,每个空腔有且只有两个出入口,并且这两个出入口不会在同一排.为了方便起见,两排出入口分别编号为1,3,5…和2,4,6…并

POJ3422 Kaka&#39;s Matrix Travels(最大费用最大流 + 拆点)

题目链接:http://poj.org/problem?id=3422 题意:有一个n*n的矩阵,格子中的元素是费用,KaKa从左上角开始出发要到达右下角,但是他只能向下走或者向右走,且走过的格子赋值为0,可以走K次,问K次后KaKa能获得的最大费用是多少? 思路:首先解释一下为什么要拆点?    因为要获得最大费用,所以假设当前步选择先下走,最终得到的结果可能不是最大值,但根据题意却把走过的格子赋为0了,这就影响了最终结果.所以进行拆点,把每个点拆成两个点,入度点和出度点,本点的入度点连接着本

HDU 2686 Matrix(最大费用最大流+拆点)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2686 和POJ3422一样 删掉K把汇点与源点的容量改为2(因为有两个方向的选择)即可 #include <iostream> #include <cstdlib> #include <cstdio> #include <cstring> #include <queue> #include <algorithm> const int ma

[BZOJ 3931][CQOI2015]网络吞吐量(SPFA+网络流)

Description 路由是指通过计算机网络把信息从源地址传输到目的地址的活动,也是计算机网络设计中的重点和难点.网络中实现路由转发的硬件设备称为路由器.为了使数据包最快的到达目的地,路由器需要选择最优的路径转发数据包.例如在常用的路由算法OSPF(开放式最短路径优先)中,路由器会使用经典的Dijkstra算法计算最短路径,然后尽量沿最短路径转发数据包.现在,若已知一个计算机网络中各路由器间的连接情况,以及各个路由器的最大吞吐量(即每秒能转发的数据包数量),假设所有数据包一定沿最短路径转发,试

POJ 3422 Kaka&#39;s Matrix Travels(最大费用最大流 + 拆点)

题目链接:http://poj.org/problem?id=3422 Description On an N × N chessboard with a non-negative number in each grid, Kaka starts his matrix travels with SUM = 0. For each travel, Kaka moves one rook from the left-upper grid to the right-bottom one, taking