SGU 226

题目大意:给出一张图,每条边都有一个颜色,求1到n的最短路,要求路径上不能有两相邻边颜色相同。

题解:本来写了个裸SPFA,WAon5看了讨论区的数据才知道不能直接判断边的颜色然后跑SPFA,应该设d[n][k]表示第n个点,由第k个颜色过来的最短路,也就是加一维跑SPFA。给我的感觉是:做不出就加一维。

%%%__debug大神。

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<queue>
#define INF 0x7fffffff/10
#define MP make_pair
#define x first
#define y second
using namespace std;
const int MAXN=201,MAXM=201*201;
typedef pair<int,int> pii;
int first[MAXN],n,m,d[MAXN][5],inq[MAXN][5],e=0;
struct Edge{
    int u,v,next,id,w;
}bian[MAXM];
void add(int a,int b,int c)
{
    ++e;bian[e].next=first[a];first[a]=e;bian[e].u=a;
    bian[e].v=b;bian[e].id=c;bian[e].w=1;
}
void SPFA()
{
    queue<pii> q;
    q.push(MP(1,4));
    inq[1][4]=1;
    while(!q.empty())
    {
        pii fr=q.front();q.pop();
        inq[fr.x][fr.y]=0;
        int u=fr.x;
        for(int i=first[u];i!=-1;i=bian[i].next)
        {
            Edge &e=bian[i];
            int v=e.v;

            if(fr.y!=e.id)
            {
                if(d[u][fr.y]+1<d[v][e.id])
                {
                    d[v][e.id]=d[u][fr.y]+1;
                    if(!inq[v][e.id])
                    {
                        inq[v][e.id]=1;
                        q.push(MP(v,e.id));
                    }
                }
            }
        }
    }
}
int main()
{
    freopen("226.in","r",stdin);
    freopen("226.out","w",stdout);
    scanf("%d %d",&n,&m);
    for(int i=1;i<=n;i++)first[i]=-1;
    for(int i=1;i<=m;i++)
    {
        int a,b,c;
        scanf("%d %d %d",&a,&b,&c);
        add(a,b,c);
    }
    for(int i=1;i<=n;i++)d[i][0]=d[i][1]=d[i][2]=d[i][3]=i==1?0:INF;
    SPFA();
    if(d[n][1]==d[n][2]&&d[n][2]==d[n][3]&&d[n][3]==INF)
       printf("-1\n");
    else
       printf("%d\n",min(d[n][1],min(d[n][2],d[n][3])));
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-14 03:38:09

SGU 226的相关文章

SGU 226.Colored graph

时间限制:0.25s 空间限制:4M 题意: 给出一个n个节点,m条边的图,每条边都有标记了编号为1,2,3三种颜色之一,现在求从1号节点到n号节点的一条最短路径的长度,要求该路径中相邻的边没有相同的颜色. Solution: 有限制条件的SPFA,要注意有时要形成环来改变路径颜色,才能到达目标点. 参考代码 #include <iostream> #include <cstring> #include <cstdio> #include <queue> #

SGU 220~229

SB题一堆,以后为了提高效率,SB题,一眼题一律不码. 220 Little Bishops 题意:求n*n的棋盘上放K个象的放法, 象可以对角线相互攻击 sb题. 221 Big Bishops 如上,一字未变,加个高精度即可,尼玛我现在高精度都能写错,还是滚回pj吧.. 222. Little Rooks 题意:n*n放车,问方案数.n最大10. 尼玛,真的滚回pj组了!?老子还是读过书的. 223 Little King 题意:如上,把车改成王. 状压直接上. 224. Little Qu

【SGU 390】Tickets (数位DP)

Tickets Description Conductor is quite a boring profession, as all you have to do is just to sell tickets to the passengers. So no wonder that once upon a time in a faraway galaxy one conductor decided to diversify this occupation. Now this conductor

ACM: SGU 101 Domino- 欧拉回路-并查集

sgu 101 - Domino Time Limit:250MS     Memory Limit:4096KB     64bit IO Format:%I64d & %I64u Description Dominoes – game played with small, rectangular blocks of wood or other material, each identified by a number of dots, or pips, on its face. The bl

SGU 116 Index of super-prime 数论+完全背包+输出方案

题目链接:http://acm.sgu.ru/problem.php?contest=0&problem=116 题意好晦涩 给你一个不超过一万的数 问它最少可以用多少个“超级素数”来表示 使“超级素数”之和等于它 如果无法这样表示 输出0 否则 按非降序形式输出方案 数论部分就模板的问题 没什么说的 完全背包方面也很常规 说说[输出方案] 背包九讲的伪码给的是二维dp[]的方法 实际上稍加改动就可以用在一维数组上 用一个rec[]记录dp[]的当前状态是从哪个状态转移而来(即上一个状态) 通过

SGU 乱搞日志

SGU 100 A+B :太神不会 SGU 101 Domino: 题目大意:有N张骨牌,两张骨牌有两面有0到6的数字,能相连当且仅当前后数字相同,问能否有将N张骨牌连接的方案?思路:裸的欧拉回路,注意自环,连通 1 //sgu101 2 #include<iostream> 3 #include<cstdio> 4 #include <math.h> 5 #include<algorithm> 6 #include<string.h> 7 #i

SGU 275 To xor or not to xor (高斯消元)

题目地址:SGU 275 首先,贪心的思想,每一二进制位上要尽量是1,而能不能是1用高斯消元来解决.当该位有一个可以使之为1的变元时,就说明这位可以为1,而且令该变元控制该位,然后向低位消元. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #include <stdlib.h>

SGU 221.Big Bishops(DP)

题意: 给一个n*n(n<=50)的棋盘,放上k个主教(斜走),求能放置的种类总数. Solution : 同SGU 220,加个高精度就好了. code #include <iostream> #include <cstdio> #include <string> #include <cstring> #include <algorithm> using namespace std; string f[2][250][250], ans;

SGU 193.Chinese Girls&#39; Amusement

/* 实际上就是求一个k,满足k<=n/2,且gcd(n,k)=1 如果n为奇数,k为[n/2] 如果n为偶数,k=n/2-1-(n/2)%2 */ #include <iostream> using namespace std; string s; void div2() { string t; int l = s.size() - 1, tem = s[0] - '0'; if (tem > 1) t += '0' + tem / 2; tem &= 1; for (i