题解

33 条题解

  • 2
    @ 2018-10-24 19:31:41

    首先,样例2应该是错的!
    然后根据题目要求存储
    最后用spfa可以秒杀

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <vector>
    #include <queue> 
    #define inf 2100000000
    #define N 105
    #define For(i,l,r) for(int i=l;i<=r;i++)
    #define Dor(i,l,r) for(int i=l;i>=r;i--)
    using namespace std;
    
    struct node{
        vector <int> to;
        vector <int> val;
    }a[N];
    int n,k,m,s,t,c[N],map[N][N],d[N];
    void spfa(int s){
        For(i,1,n) d[i]=inf;
        queue <int> q;
        q.push(s);
        d[s]=0;
        while(!q.empty()){
            int x=q.front();
            q.pop();
            for(int i=0;i<a[x].to.size();i++){
                int v=a[x].to[i];
                int w=a[x].val[i];
                if (d[v]>d[x]+w){
                    d[v]=d[x]+w;
                    q.push(v);
                }
            }
        }
    } 
    int main(){ 
        scanf("%d%d%d%d%d",&n,&k,&m,&s,&t);
        For(i,1,n) scanf("%d",&c[i]);
        For(i,1,k) For(j,1,k) scanf("%d",&map[i][j]);
        For(i,1,m){
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            if (!map[c[x]][c[y]]) a[x].to.push_back(y),a[x].val.push_back(z);
            if (!map[c[y]][c[x]]) a[y].to.push_back(x),a[y].val.push_back(z);
        }
        spfa(s);
        if (d[t]==inf){
            printf("-1\n");
        }else printf("%d\n",d[t]);
        return 0;
    }
    
  • 2
    @ 2017-05-01 16:40:07

    文化之旅

    (NOIP2012 普及组 T4 )

    题目描述

    有一位使者要游历各国,他每到一个国家,都能学到一种文化,但他不愿意学习任何一种文化超过一次(即如果他学习了某种文化,则他就不能到达其他有这种文化的国家)。不同的国家可能有相同的文化。不同文化的国家对其他文化的看法不同,有些文化会排斥外来文化(即如果他学习了某种文化,则他不能到达排斥这种文化的其他国家)。现给定各个国家间的地理关系,各个国家的文化,每种文化对其他文化的看法,以及这位使者游历的起点和终点(在起点和终点也会学习当地的文化),国家间的道路距离,试求从起点到终点最少需走多少路。

    输入输出格式

    输入格式:
    第一行为五个整数 N,K,M,S,T,每两个整数之间用一个空格隔开,依次代表国家个数(国家编号为 1 到 N),文化种数(文化编号为 1 到 K),道路的条数,以及起点和终点的编号(保证 S 不等于 T);
    第二行为 N 个整数,每两个整数之间用一个空格隔开,其中第 i 个数 Ci,表示国家 i的文化为 Ci。
    接下来的 K 行,每行 K 个整数,每两个整数之间用一个空格隔开,记第 i 行的第 j 个数为 aij,aij= 1 表示文化 i 排斥外来文化 j(i 等于 j 时表示排斥相同文化的外来人),aij= 0 表示不排斥(注意 i 排斥 j 并不保证 j 一定也排斥 i)。
    接下来的 M 行,每行三个整数 u,v,d,每两个整数之间用一个空格隔开,表示国家 u与国家 v 有一条距离为 d 的可双向通行的道路(保证 u 不等于 v,两个国家之间可能有多条道路)。

    输出格式:
    输出只有一行,一个整数,表示使者从起点国家到达终点国家最少需要走的距离数(如果无解则输出-1)。

    输入输出样例

    输入样例#1:
    2 2 1 1 2
    1 2
    0 1
    1 0
    1 2 10
    输出样例#1:
    -1
    输入样例#2:
    2 2 1 1 2
    1 2
    0 1
    0 0
    1 2 10
    输出样例#2:
    10
    说明

    输入输出样例说明1
    由于到国家 2 必须要经过国家 1,而国家 2 的文明却排斥国家 1 的文明,所以不可能到达国家 2。

    输入输出样例说明2
    路线为 1 -> 2

    数据范围
    对于 100%的数据,有 2≤N≤100 1≤K≤100 1≤M≤N2 1≤ki≤K 1≤u, v≤N 1≤d≤1000 S≠T 1≤S,T≤N

    来源
    NOIP 2012 普及组 第四题

    今天我们借助这道普及组T4来见识一下DFS(蒟蒻)与SPFA(大佬)的差别(似乎没有什么卵用)。
    很显然,这道题是一道最短路的题目,作为蒟蒻,可能会在考试时使用DFS。

    DFS代码

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    using namespace std;
    int i,j,m,n,u,v,d,t,s,k,minn=0x7f7f7f7f;
    int b[101][101],map[101][101];
    int bo[101],jl[101];

    struct data
    {
    int cul;
    }a[105];

    int readd()
    {
    int aans=0;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    ch=getchar();
    while(ch>='0'&&ch<='9')
    {
    aans*=10;
    aans+=ch-'0';
    ch=getchar();
    }
    return aans;
    }

    void dfs(int x,int ans)
    {
    if(jl[x])
    {
    if(jl[x]>ans)
    jl[x]=ans;
    else
    return;}
    if(x==t) {minn=min(minn,ans);return;}
    for(int i=1;i<=n;i++)
    {
    if(!bo[i]&&i!=x&&map[x][i])
    {
    bo[i]=1;
    dfs(i,ans+map[x][i]);
    bo[i]=0;}
    }
    }

    int main()
    {
    n=readd();k=readd();m=readd();s=readd();t=readd();
    for(i=1;i<=n;i++)
    a[i].cul=readd();
    for(i=1;i<=k;i++)
    for(j=1;j<=k;j++)
    b[i][j]=readd();
    for(i=1;i<=m;i++)
    {
    u=readd();v=readd();d=readd();
    if(!b[a[v].cul][a[u].cul])
    map[u][v]=d;
    else
    map[u][v]=0;
    if(!b[a[u].cul][a[v].cul])
    map[v][u]=d;
    else
    map[v][u]=0;
    }
    bo[s]=1;
    dfs(s,0);
    if(minn==0x7f7f7f7f)
    cout<<-1;
    else
    cout<<minn;
    }
    DFS(74lines)原理不想赘述,接下来看看SPFA(105lines)的表现。

    SPFA代码

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<deque>
    using namespace std;
    int i,j,m,n,u,v,d,t,s,k,minn=0x7f7f7f7f;
    int head[101];
    int b[101][101];
    int us[101];
    int dis[101];
    struct data
    {
    int cul;
    }a[105];

    struct node
    {
    int yy;
    int va;
    struct node *nxt;
    }map[10005];

    int readd()
    {
    int aans=0;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    ch=getchar();
    while(ch>='0'&&ch<='9')
    {
    aans*=10;
    aans+=ch-'0';
    ch=getchar();
    }
    return aans;
    }

    int spfa(int x)
    {
    us[x]=1;
    deque<int>q;
    dis[x]=0;
    q.push_front(x);
    struct node *p;
    while(!q.empty())
    {
    x=q.front();
    p=&map[head[x]];
    us[x]=0;
    q.pop_front();

    while(p->yy!=0)
    {

    if(dis[x]+p->va<dis[p->yy])
    {
    dis[p->yy]=dis[x]+p->va;
    if(!us[p->yy])
    {
    if(q.empty()||dis[q.front()]>dis[p->yy])
    q.push_front(p->yy);
    else
    q.push_back(p->yy);
    us[p->yy]=1;
    }
    }
    p=p->nxt;
    }
    }

    }

    int main()
    {
    n=readd();k=readd();m=readd();s=readd();t=readd();
    for(i=1;i<=n;i++)
    a[i].cul=readd();
    for(i=1;i<=k;i++)
    for(j=1;j<=k;j++)
    b[i][j]=readd();
    int tem=1;
    for(i=1;i<=m;i++)
    {
    u=readd();v=readd();d=readd();
    if(!b[a[u].cul][a[v].cul])
    {
    map[tem].va=d,map[tem].yy=v;
    map[tem].nxt=&map[head[u]],head[u]=tem;
    tem++;}
    if(!b[a[v].cul][a[u].cul])
    {
    map[tem].va=d,map[tem].yy=u;
    map[tem].nxt=&map[head[v]],head[v]=tem;
    tem++;}
    }
    memset(dis,0x7f7f7f7f,sizeof(dis));
    spfa(s);
    if(dis[t]!=0x7f7f7f7f)
    cout<<dis[t];
    else
    cout<<-1;
    return 0;
    }
    虽然多写了一些不该写的东西,但是值得说明的是,这个代码我使用了SPFA的SLF优化。
    简要说说这个的思路,就是记录每两个国家的文化之间是否冲突,如果冲突就将距离设置为一个MAX,反而反之。最后输出时看看dis[t]是否是MAX,若是直接输出-1,反之输出计算值。值得注意的是,题干中所描述的两个文化冲突,是国家1排斥国家2,所以不能从国家2到国家1,这一点如果没发现的话,好像也能过。

    结果

    下面看看结果。

    DFS

    测试点#culture1.in 结果:AC 内存使用量: 256kB 时间使用量: 1ms
    测试点#culture10.in 结果:TLE 内存使用量: 364kB 时间使用量: 1000ms
    测试点#culture2.in 结果:AC 内存使用量: 256kB 时间使用量: 0ms
    测试点#culture3.in 结果:AC 内存使用量: 256kB 时间使用量: 0ms
    测试点#culture4.in 结果:AC 内存使用量: 256kB 时间使用量: 1ms
    测试点#culture5.in 结果:AC 内存使用量: 256kB 时间使用量: 69ms
    测试点#culture6.in 结果:TLE 内存使用量: 256kB 时间使用量: 1000ms
    测试点#culture7.in 结果:TLE 内存使用量: 256kB 时间使用量: 1000ms
    测试点#culture8.in 结果:TLE 内存使用量: 360kB 时间使用量: 1000ms
    测试点#culture9.in 结果:TLE 内存使用量: 364kB 时间使用量: 1000ms

    SPFA

    测试点#culture1.in 结果:AC 内存使用量: 256kB 时间使用量: 1ms
    测试点#culture10.in 结果:AC 内存使用量: 364kB 时间使用量: 1ms
    测试点#culture2.in 结果:AC 内存使用量: 256kB 时间使用量: 0ms
    测试点#culture3.in 结果:AC 内存使用量: 256kB 时间使用量: 0ms
    测试点#culture4.in 结果:AC 内存使用量: 256kB 时间使用量: 0ms
    测试点#culture5.in 结果:AC 内存使用量: 256kB 时间使用量: 1ms
    测试点#culture6.in 结果:AC 内存使用量: 364kB 时间使用量: 0ms
    测试点#culture7.in 结果:AC 内存使用量: 256kB 时间使用量: 0ms
    测试点#culture8.in 结果:AC 内存使用量: 364kB 时间使用量: 1ms
    测试点#culture9.in 结果:AC 内存使用量: 360kB 时间使用量: 1ms

    结束语

    由此观之,DFS适合于考试没时间的时候做,可以过一半,但是如果时间充足的话,还是用SPFA比较妥。

  • 1
    @ 2021-08-30 07:42:58
    #include <bits/stdc++.h>
    using namespace std;
    
    int n,k,m,s,t,c[120],g[120][120],f[120][120],aa,bb,cc;
    int main(){
        cin>>n>>k>>m>>s>>t;
        for(register int i=1; i<=n; i++)
            for(register int j=1; j<=n; j++)
                f[i][j]=21743822;
        for(register int i=1; i<=n; i++)
            cin>>c[i];
        for(register int i=1; i<=k; i++)
            for(register int j=1; j<=k; j++)
                cin>>g[i][j];
        for(register int i=1;i<=m;i++){
            cin>>aa>>bb>>cc;
            if(!g[c[bb]][c[aa]] && c[bb]!=c[aa])
                f[aa][bb]=min(f[aa][bb],cc);
            if(!g[c[aa]][c[bb]] && c[bb]!=c[aa])
                f[bb][aa]=min(f[bb][aa],cc);
        }
        if(c[s]==c[t]){
            cout<<-1;
            return 0;
        }
        for(register int i=1; i<=n; i++)
            for(register int j=1; j<=n; j++)
                if(i!=j)
                    for(register int k=1; k<=n; k++)
                        if(j!=k && i!=k)
                            if(f[i][k]+f[k][j]<f[i][j])
                                f[i][j]=f[i][k]+f[k][j];
        if(f[s][t]==21743822)
            cout<<-1;
        else
            cout<<f[s][t];
        return 0;
    }
    
  • 0
    @ 2017-10-08 21:05:57

    简单的Floyed ヘ( ̄ω ̄ヘ)

    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #define INF 1000000
    using namespace std;
    int main()
    {
        int c[105];
        int a[105][105];
        int dis[105][105];
        bool jl[105][105];
        memset(jl,0,sizeof(jl));
        int n,k,m,s,t,u,v,d;
        cin>>n>>k>>m>>s>>t;
        for(int i=1;i<=n;++i)
        cin>>c[i];
        for(int i=1;i<=k;++i)
        {
            for(int j=1;j<=k;++j)
            {
                cin>>a[i][j];
            }
        }
        for(int i=1;i<=n;++i)
        {
            for(int j=1;j<=n;++j)
            {
                if(i==j)
                dis[i][j]=0;
                else
                dis[i][j]=INF;
            }
        }
        for(int i=1;i<=m;++i)
        {
            cin>>u>>v>>d;
            if(a[c[u]][c[v]]==0)
            dis[v][u]=d;
            if(a[c[v]][c[u]]==0)
            dis[u][v]=d;
        }
        for(int l=1;l<=n;++l)
        {
            for(int i=1;i<=n;++i)
            {
                for(int j=1;j<=n;++j)
                {
                    if(dis[i][l]+dis[l][j]<dis[i][j]&&a[c[l]][c[i]]==0&&a[c[j]][c[l]]==0)
                    {
                        dis[i][j]=dis[i][l]+dis[l][j];
                        jl[i][j]=1;
                    }               
                }
            }
        }
        if(jl[s][t]==1)
        cout<<dis[s][t];
        else cout<<"-1";
        return 0;
    }   
    
  • 0
    @ 2017-08-21 20:10:11

    什么鬼,,我这个folyd 样例第二个没过啊。。。居然对了。。不科学 。。有人给我解释下么。。。

    
    Var
            n,k,s,m,t,x,z,y,i,j:longint;
            f,a:array[1..1000,1..1000]of longint;
            b:array[1..1000]of longint;
    Begin
            readln(n,k,m,s,t);
            for i:=1 to n do
                    read(b[i]);
            for i:=1 to k do
                    for j:=1 to k do
                            read(a[i,j]);
    
            for i:=1 to n do
                    for j:=1 to n do
                            f[i,j]:=maxint;
            for i:=1 to m do
            begin
                    readln(x,y,z);
                    if a[b[x],b[y]]=0 then
                            f[x,y]:=z;
                    if a[b[y],b[x]]=0 then
                            f[y,x]:=z;
            end;
    
            for i:=1 to n do
                    for j:=1 to n do
                            if i<>j then
                                    for k:=1 to n do
                                            if (a[b[k],b[i]]=0) and (a[b[j],b[k]]=0) and (k<>j) and
                                               (f[i,j]>f[i,k]+f[k,j]) then
                                                    f[i,j]:=f[i,k]+f[k,j];
    
            if f[s,t]=maxint then
                    writeln(-1)
            else
                    writeln(f[s,t]);
            readln;
    End.
    
    
  • 0
    @ 2016-07-27 11:48:53
    floyd秒杀
    记录信息
    评测状态    Accepted
    题目  P1794 文化之旅
    递交时间    2016-07-27 11:47:13
    代码语言    C++
    评测机 ShadowShore
    消耗时间    30 ms
    消耗内存    632 KiB
    评测时间    2016-07-27 11:47:17
    评测结果
    编译成功
    
    测试数据 #0: Accepted, time = 0 ms, mem = 632 KiB, score = 10
    测试数据 #1: Accepted, time = 0 ms, mem = 632 KiB, score = 10
    测试数据 #2: Accepted, time = 0 ms, mem = 632 KiB, score = 10
    测试数据 #3: Accepted, time = 15 ms, mem = 632 KiB, score = 10
    测试数据 #4: Accepted, time = 0 ms, mem = 628 KiB, score = 10
    测试数据 #5: Accepted, time = 15 ms, mem = 628 KiB, score = 10
    测试数据 #6: Accepted, time = 0 ms, mem = 628 KiB, score = 10
    测试数据 #7: Accepted, time = 0 ms, mem = 632 KiB, score = 10
    测试数据 #8: Accepted, time = 0 ms, mem = 628 KiB, score = 10
    测试数据 #9: Accepted, time = 0 ms, mem = 632 KiB, score = 10
    Accepted, time = 30 ms, mem = 632 KiB, score = 100
    代码
    #include <bits/stdc++.h>
    using std :: min;
    const int INF = 999999;
    int n,k,m,s,t,dist[101][101],c[101],a[101][101];
    int main() {
      scanf("%d%d%d%d%d",&n,&k,&m,&s,&t);
      for (int i = 1;i <= n;i++)
        for (int j = 1;j <= n;j++) dist[i][j] = INF;
      for (int i = 1;i <= n;i++) scanf("%d",&c[i]);
      for (int i = 1;i <= k;i++)
        for (int j = 1;j <= k;j++)
          scanf("%d",&a[i][j]);
      for (int i = 1;i <= m;i++) {
        int a1,b1,c1;
        scanf("%d%d%d",&a1,&b1,&c1);
        dist[a1][b1] = dist[b1][a1] = c1;
      }
      for (int i = 1;i <= n;i++)
        for (int j = 1;j <= n;j++)
          if (a[c[i]][c[j]]) dist[i][j] = INF;
      for (int k = 1;k <= n;k++)      //floyd
        for (int i = 1;i <= n;i++)
          for (int j = 1;j <= n;j++) dist[i][j] = min(dist[i][j],dist[i][k]+dist[k][j]);
      if (dist[s][t] == INF) printf("%d",-1);
      else printf("%d",dist[t][s]);
    }
    
    • @ 2016-08-17 17:30:53

      这用户名劲啊!

  • 0
    @ 2016-07-20 17:43:28

    这题不加不能重复学习一样过 #手动滑稽
    #include <cstdio>
    #include <cstring>
    #include <queue>

    using std::queue;

    int n,k,m,S,T;
    int cul[110],ag[110][110];
    int acc[110]={0};

    struct edge{
    int d,v;
    struct edge *link;
    };

    int top=1;
    edge graph[110]={0};
    edge node[110*110];

    void read(int s,int d,int v){
    edge *l;
    l=&node[top];
    l->d=d;
    l->v=v;
    l->link=graph[s].link;
    graph[s].link=l;
    top++;
    }

    void build(){
    int s,d,v;
    for(int i=1;i<=m;i++){
    scanf("%d%d%d",&s,&d,&v);
    read(s,d,v);
    read(d,s,v);
    }
    }

    int judge(int learn[],int d){
    int flag=0;
    for(int i=1;i<=k;i++)
    flag+=learn[i]==1&&ag[cul[d]][i]==1;
    flag+=learn[cul[d]]==1;
    if(flag>1)
    flag=1;
    return flag;
    }

    int ans=999999999;
    int vis[110]={0};
    int learn[110]={0};

    void dfs2(int s,int dist){
    if(s==T){
    if(dist<ans)
    ans=dist;
    }
    edge *l;
    l=graph[s].link;
    while(l){
    if(!vis[l->d]&&judge(learn,l->d)==0){
    vis[l->d]=1;
    learn[cul[l->d]]=1;
    dfs2(l->d,dist+l->v);
    vis[l->d]=0;
    learn[cul[l->d]]=1;
    }
    l=l->link;
    }
    }

    int main(){
    //freopen("in.txt","r",stdin);
    scanf("%d%d%d%d%d",&n,&k,&m,&S,&T);
    for(int i=1;i<=n;i++)
    scanf("%d",&cul[i]);
    for(int i=1;i<=k;i++)
    for(int j=1;j<=k;j++)
    scanf("%d",&ag[i][j]);
    build();

    learn[cul[S]]=1;
    vis[S]=1;
    dfs2(S,0);

    if(ans==999999999){
    printf("-1");
    return 0;
    }
    printf("%d",ans);
    return 0;
    }

    • @ 2016-09-16 11:38:09

      没错,当时我就被震惊了

  • 0
    @ 2016-07-15 12:49:37
    #include<iostream>
    #include<algorithm>
    #include<queue>
    #include<string>
    #include<map>
    #include<vector>
    #include<set>
    #include<sstream>
    #include<stack>
    #include<cstring>
    #include<cstdio>
    #include<cstdlib>
    #include<ctime>
    #include<cmath>
    #include<climits>
    #include<cctype>
    using namespace std;
    struct Snode {
        int v,w;
        Snode() {}
        Snode(int v0,int w0):v(v0),w(w0) {}
    };
    int n,k,m,s,t,c[101],dist[101],dis[1000001],pre[1000001],num[1000001],head=0,tail=1;
    vector<int> avoid[101];
    vector<Snode> son[101];
    bool vist[101];
    int main() {
        //freopen("262.in","r",stdin);
        //freopen("262.out","w",stdout);
        ios::sync_with_stdio(false);
        cin.tie(0);
        cin>>n>>k>>m>>s>>t;
        for(int i=1;i<=n;++i)
            cin>>c[i];
        for(int i=1,tmp;i<=k;++i)
            for(int j=1;j<=k;++j) {
                cin>>tmp;
                if(tmp) avoid[j].push_back(i);
            }
        for(int i=1,a,b,v;i<=m;++i) {
            cin>>a>>b>>v;
            son[a].push_back(Snode(b,v));
            son[b].push_back(Snode(a,v));
        }
        memset(dist,127,sizeof dist);
        queue<int> q;
        dist[t]=0;
        vist[t]=true;
        q.push(t);
        while(!q.empty()) {
            int now=q.front(); q.pop();
            vist[now]=false;
            for(int i=0;i<son[now].size();++i) {
                Snode tmp=son[now][i];
                if(dist[tmp.v]>dist[now]+tmp.w) {
                    dist[tmp.v]=dist[now]+tmp.w;
                    if(!vist[tmp.v]) {
                        vist[tmp.v]=true;
                        q.push(tmp.v);
                    }
                }
            }
        }
        int ans=-1;
        memset(dis,127,sizeof dis);
        dis[head]=0;
        pre[head]=-1;
        num[head]=s;
        int cnt=0;
        while(head<tail&&cnt<10000) {
            int now=num[head++];
            if(now==t) ans=ans==-1?dis[head-1]:min(ans,dis[head-1]);
            for(int i=0;i<son[now].size();++i) {
                int x=son[now][i].v;
                for(int j=head-1;j!=-1;j=pre[j]) {
                    for(k=0;k<avoid[c[num[j]]].size();++k)
                        if(avoid[c[num[j]]][k]==c[x])
                            goto end;
                    if(c[num[j]]==c[x])
                        goto end;
                }
                if(ans==-1||dist[x]+dis[head-1]<ans) {
                    pre[tail]=head-1;
                    num[tail]=x;
                    dis[tail]=dis[head-1]+son[now][i].w;
                    ++tail;
                }
                end:;
            }
            ++cnt;
        }
        cout<<ans<<endl;
        return 0;
    }
    
  • 0
    @ 2016-04-24 15:48:03
    #include<iostream>
    #include<cstdio>
    #include<queue>
    #include<vector>
    using namespace std;
    
    const int maxn = 110;
    const int maxx = 999999;
    int n, k, m, s, t;
    int c[maxn] = {0};
    int d[maxn] = {0};
    int a[maxn][maxn] = {0};
    bool in[maxn] = {0};
    bool v[maxn] = {0};
    queue<int> q;
    
    struct edge {
        int from, to, dist;
        edge (int a, int b, int c) : from(a), to(b), dist(c) {}
    };
    
    vector<int> g[maxn];
    vector<edge> edges;
    
    void add (int from, int to, int dist) {
        edges.push_back(edge(from, to, dist));
        int e = edges.size();
        g[from].push_back(e-1);
    }
    
    void read (void) {
        cin >> n >> k >> m >> s >> t;
        for (int i = 1; i <= n; i++) cin >> c[i];
        for (int i = 1; i <= k; i++) 
            for (int j = 1; j <= k; j++) 
                cin >> a[i][j];
        int u, v, d;
        for (int i = 0; i < m; i++) {
            cin >> u >> v >> d;
            add (u, v, d);
            add (v, u, d);
        }   
    }
    
    void spfa (void) {
        for (int i = 1; i <= n; i++) { d[i] = maxx; in[i] = false;}
        d[s] = 0;
        q.push(s);
        in[s] = true;
        int e;
        edge p();
        while (!q.empty()) {
            e = q.front();
            q.pop();
            in[e] = false;
            for (int i = 0; i < g[e].size(); i++) {
                edge &p = edges[g[e][i]];
                if (d[p.to] > d[e] + p.dist && c[p.to] != c[s] && c[p.to] != c[e] && !a[c[p.to]][c[s]] && !a[c[p.to]][c[e]]) {
                    d[p.to] = d[e] + p.dist;
                    v[p.to] = true;
                    if (!in[p.to]) {
                        q.push(p.to);
                        in[p.to] = true;
                    }
                }
            }
        }
    }
    
    int main () 
    {
        //freopen ("in.txt", "r", stdin);
        read();
        spfa();
        if (!v[t]) cout << -1;
        else cout << d[t];
        return 0;
    }
    
    • @ 2016-04-24 15:49:50

      数据好水,一开始判断排斥的地方全部打错都得了九十分,我还以为其他地方错了

    • @ 2016-06-14 17:53:36

      然而只是数据水,算法是错的
      读入:
      5 5 4 1 4
      1 2 3 4 5
      0 0 0 0 0
      0 0 0 0 0
      0 0 0 0 0
      0 1 0 0 0
      0 0 0 0 0
      1 2 1
      2 3 1
      3 4 1
      4 5 1

      正确输出:
      -1

      程序输出:
      3

  • 0
    @ 2016-03-10 22:51:12
    uses math;
    var n,k,m,s,t:longint;
      i,j,u,v,d:longint;
      b:boolean;
    
      vd:array[0..200] of boolean;
      cul:array[0..200] of longint;        //各国文化
      lea:array[0..200] of set of 0..200;  //到某国时已经学习过的文化
      map:array[0..200,0..200] of longint; //地图(道路)
      aga:array[0..200,0..200] of longint; //文化排斥
      mc:array[0..200] of longint;         //最短路
    
    begin
      //预处理
      fillchar(vd,sizeof(vd),false);
      read(n,k,m,s,t);
      for i:=1 to n do mc[i]:=maxint;
      for i:=1 to n do
        for j:=1 to n do map[i,j]:=maxint;
    
      for i:=1 to n do read(cul[i]);
      for i:=1 to k do
        for j:=1 to k do
          read(aga[i,j]);
      for i:=1 to k do aga[i,i]:=1;
      for i:=1 to m do begin
        read(u,v,d);
        map[u,v]:=min(map[u,v],d);
        map[v,u]:=map[u,v];
      end;
    
      //初始化
      mc[s]:=0;
      lea[s]:=[cul[s]];
    
      //dijkstra最短路
      while true do begin
        u:=-1;
        for i:=1 to n do
          if not vd[i] and ((u=-1) or (mc[i]<mc[u])) then u:=i;
        if u=-1 then break;
    
        vd[u]:=true;
    
        //维护mc
        for i:=1 to n do
          if (mc[i]>(mc[u]+map[u,i])) then begin
            //判断排斥
            b:=false;
            for j:=1 to n do
              if (aga[cul[i],j]=1) and (j in lea[u]) then begin b:=true;break end;
            //更新
            if not b then begin
              mc[i]:=mc[u]+map[u,i];
              lea[i]:=lea[u]+[cul[i]];
            end;
          end;
    
      end;
      //输出
      if mc[t]=maxint then write(-1)
      else write(mc[t]);
    end.
    
  • 0
    @ 2016-02-08 13:42:43

    看见最后一个点超时,干脆懒得写了,直接开 windows API...

    if(GetTickCount()-beginTime >= 900)
    return;

    • @ 2016-02-17 10:33:52

      最后一个点
      1750<m<1800
      -1

  • 0
    @ 2016-01-31 21:14:12

    #include <cstdio>
    #include <cstring>
    using namespace std;
    struct data{
    int b[300];
    };
    int first[30000],next[30000],last[30000],a[30000],c[30000],b[300][300],d[300],e[300],o[300],p[700];
    data f[300];
    int i,j,k,n,m,x,y,t,s,l,q,q1,h;
    int push(int x){
    if (o[x]==1) return 0;
    q1++;
    o[x]=1;
    p[q1]=x;
    }
    int add(int x,int y,int t){
    q++;
    a[q]=y;
    c[q]=t;
    if (first[x]==0) first[x]=q;
    else next[last[x]]=q;
    last[x]=q;
    }
    int main(){
    //freopen("culture.in","r",stdin);
    // freopen("culture.out","w",stdout);
    scanf("%d%d%d%d%d",&n,&k,&m,&s,&t);
    for (i=1;i<=n;i++) scanf("%d",&e[i]);
    for (i=1;i<=k;i++)
    for (j=1;j<=k;j++){
    scanf("%d",&x);
    b[i][j]=x;
    }
    for (i=1;i<=m;i++){
    scanf("%d%d%d",&x,&y,&l);
    add(x,y,l);
    add(y,x,l);
    }
    for (i=1;i<=n;i++) d[i]=1000000000;
    d[s]=0;
    h=0;
    push(s);
    f[s].b[e[s]]=1;
    while (h<q1){
    h++;
    x=first[p[h]];
    o[p[h]]=0;
    while (x!=0){
    if (d[p[h]]+c[x]<d[a[x]]&&b[e[a[x]]][e[p[h]]]==0&&f[p[h]].b[e[a[x]]]!=1){
    d[a[x]]=d[p[h]]+c[x];
    f[a[x]]=f[p[h]];
    f[a[x]].b[e[a[x]]]=1;
    push(a[x]);
    }
    x=next[x];
    }
    }
    if (d[t]==1000000000) printf("-1");
    else printf("%d",d[t]);
    }

  • 0
    @ 2015-06-04 15:34:39

    记录信息
    评测状态 Accepted
    题目 P1794 文化之旅
    递交时间 2015-06-04 15:28:52
    代码语言 C++
    评测机 Jtwd2
    消耗时间 33 ms
    消耗内存 572 KiB
    评测时间 2015-06-04 15:28:57
    评测结果
    编译成功

    测试数据 #0: Accepted, time = 0 ms, mem = 572 KiB, score = 10
    测试数据 #1: Accepted, time = 0 ms, mem = 572 KiB, score = 10
    测试数据 #2: Accepted, time = 0 ms, mem = 572 KiB, score = 10
    测试数据 #3: Accepted, time = 0 ms, mem = 572 KiB, score = 10
    测试数据 #4: Accepted, time = 0 ms, mem = 568 KiB, score = 10
    测试数据 #5: Accepted, time = 3 ms, mem = 568 KiB, score = 10
    测试数据 #6: Accepted, time = 0 ms, mem = 568 KiB, score = 10
    测试数据 #7: Accepted, time = 0 ms, mem = 572 KiB, score = 10
    测试数据 #8: Accepted, time = 325 ms, mem = 568 KiB, score = 10
    测试数据 #9: Accepted, time = 15 ms, mem = 572 KiB, score = 10
    Accepted, time = 343 ms, mem = 572 KiB, score = 100

    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #include <vector>
    #define MAXN 110
    #define MAX 1000000
    #define INF 10000000
    using namespace std;
    int ma[MAXN][MAXN];
    int c[MAXN];
    int f[MAXN][MAXN];
    int n,m,k,s,t;
    int main(){

    for (int i=0;i<105;i++)
    fill(ma[i],ma[i]+101,INF);

    scanf("%d%d%d%d%d",&n,&k,&m,&s,&t);
    for (int i=0;i<n;i++)
    scanf("%d",&c[i]);

    for (int i=0;i<k;i++)
    for (int j=0;j<k;j++)
    scanf ("%d",&f[i][j]);
    int x,y,z;
    for(int i=1;i<=m;i++){

    cin>>x>>y>>z;
    if (z<ma[x][y])
    ma[x][y]=z;
    }

    for (int k=0;k<n;k++)
    for (int i=0;i<n;i++)
    for (int j=0;j<n;j++){
    ma[i][j]=min(ma[i][j],ma[i][k]+ma[k][j]);

    }

    printf ("%d",ma[s][t]);
    return 0;
    }

    纯属娱乐

  • 0
    @ 2015-04-11 13:39:38

    嗯... DFS拿了50分。醉了。

    谁能详细的剖析下这个题目么?
    那个预估路线具体是什么样啊??

    他喵的我在想这题用集合判断文化冲突不是很逆天么.......求并交集太简单了啊

  • 0
    @ 2014-08-05 15:26:19

    普及组的题怎么能这么水……
    去NOI官网拉了个数据看了一下,完全不涉及是否文化排斥好吗……
    这数据规模,几分钟打个Floyd就过了。

  • 0
    @ 2014-04-20 18:57:20

    var
    n,k,m,s,t,i,j,u,v,d,a:longint;
    f:array[0..1001,0..1001] of boolean;
    mp:array[0..1001,0..1001] of longint;
    cu:array[0..1001] of longint;
    function min(a,b:longint):longint;
    begin
    if a<b then exit(a)
    else exit(b);
    end;
    begin
    readln(n,k,m,s,t);
    for i:=1 to n do
    read(cu[i]);
    fillchar(f,sizeof(f),false);
    for i:=1 to k do
    for j:=1 to k do
    begin
    read(a); if a=1 then f[i,j]:=true;
    end;
    for i:=1 to n do
    for j:=1 to n do
    mp[i,j]:=100000;
    for i:=1 to m do
    begin
    readln(u,v,d);
    if not(f[cu[v],cu[u]]) then mp[u,v]:=min(mp[u,v],d);
    if not(f[cu[u],cu[v]]) then mp[v,u]:=min(mp[v,u],d);
    end;
    for k:=1 to n do
    for i:=1 to n do
    for j:=1 to n do
    if not(f[cu[j],cu[i]]) then
    mp[i,j]:=min(mp[i,j],mp[i,k]+mp[k,j]);
    if mp[s,t]=100000 then writeln('-1')
    else writeln(mp[s,t]);
    end.

  • 0
    @ 2014-02-04 00:27:46

    很显然本题搜索的约束条件很强,可行性剪枝可以排除大部分情况,只要到达目标状态也可以用最优性剪枝排除大部分情况,所以无解的情况是最耗时的,在搜索前先用一个快速判断的函数预先判断可不可以到达终点就可以了
    var n,m,k,s,t,min:longint;
    c:array[1..100] of longint;
    a:array[1..100,1..100] of boolean;
    map:array[1..100,1..100] of longint;
    p,f:array[1..100] of boolean;
    procedure ini;
    var i,j,u,v,d:longint;
    begin
    readln(n,k,m,s,t);
    for i:=1 to n do read(c[i]);
    readln;
    for i:=1 to k do begin
    for j:=1 to k do begin
    read(u);
    if u=1 then a[i,j]:=true;
    end;
    readln;
    end;
    for i:=1 to m do begin
    readln(u,v,d);
    map[u,v]:=d;
    map[v,u]:=d;
    end;
    min:=maxlongint;
    p[c[s]]:=true;
    end;
    function can(now:longint):boolean;
    var i:longint;
    begin
    if now=s then exit(true);
    for i:=1 to n do if(map[i,now]>0)and(c[i]<>c[now])and(a[c[now],c[i]]=false)and(f[i]=false)then begin
    f[i]:=true;
    if can(i)=true then exit(true);
    f[i]:=false;
    end;
    can:=false;
    end;
    procedure search(now,value:longint);
    var i,j:longint;
    tt:boolean;
    begin
    if now=t then begin
    if value<min then min:=value;
    exit;
    end;
    if value>=min then exit;
    for i:=1 to n do begin
    if p[c[i]]=true then continue;
    tt:=false;
    for j:=1 to n do if (p[c[j]]=true)and(a[c[i],c[j]]=true) then begin
    tt:=true;
    break;
    end;
    if tt=true then continue;
    if map[now,i]=0 then continue;
    if value+map[now,i]>=min then continue;
    p[c[i]]:=true;
    search(i,value+map[now,i]);
    p[c[i]]:=false;
    end;
    end;
    begin
    ini;
    f[n]:=true;
    if can(t)=false then begin
    writeln(-1);
    halt;
    end;
    search(s,0);
    p[c[s]]:=false;
    if min<maxlongint then writeln(min) else writeln(-1);
    end.

  • 0
    @ 2014-01-26 16:32:56

    别人说SPFA做不了。其实可以的。用pre数组记录前驱,用递归判断文化是否有冲突。剩余就是最短路。

    测试数据 #0: Accepted, time = 0 ms, mem = 1220 KiB, score = 10
    测试数据 #1: Accepted, time = 0 ms, mem = 1216 KiB, score = 10
    测试数据 #2: Accepted, time = 0 ms, mem = 1224 KiB, score = 10
    测试数据 #3: Accepted, time = 0 ms, mem = 1220 KiB, score = 10
    测试数据 #4: Accepted, time = 0 ms, mem = 1224 KiB, score = 10
    测试数据 #5: Accepted, time = 0 ms, mem = 1220 KiB, score = 10
    测试数据 #6: Accepted, time = 0 ms, mem = 1220 KiB, score = 10
    测试数据 #7: Accepted, time = 0 ms, mem = 1220 KiB, score = 10
    测试数据 #8: Accepted, time = 0 ms, mem = 1220 KiB, score = 10
    测试数据 #9: Accepted, time = 0 ms, mem = 1220 KiB, score = 10
    Accepted, time = 0 ms, mem = 1224 KiB, score = 100

    var n,k,m,s,t,i,j,u,head,tail,x,y:longint;
    culture,pre,dis:array[1..200] of longint;
    team:array[1..205] of longint;
    fl:array[1..200] of boolean;
    a:array[1..200,0..200] of longint;
    w:array[1..200,1..200] of longint;
    b:array[1..200,1..200] of integer;
    function pd(k:longint):boolean;
    begin
    pd:=true;
    if pre[k]=0 then
    exit(true);
    if b[culture[a[u,i]],culture[k]]=1 then
    exit(false);
    exit(pd(pre[k]));
    end;
    begin
    readln(n,k,m,s,t);
    for i:=1 to n do
    read(culture[i]);
    for i:=1 to k do
    begin
    for j:=1 to k do
    read(b[i,j]);
    b[i,i]:=1;
    end;
    for i:=1 to m do
    begin
    readln(x,y,w[x,y]);
    w[y,x]:=w[x,y];
    inc(a[x,0]);
    a[x,a[x,0]]:=y;
    inc(a[y,0]);
    a[y,a[y,0]]:=x;
    end;
    fillchar(pre,sizeof(pre),0);
    fillchar(team,sizeof(team),0);
    fillchar(fl,sizeof(fl),false);
    for i:=1 to n do
    dis[i]:=maxlongint div 3;
    dis[s]:=0;team[1]:=s;fl[s]:=true;head:=0;tail:=1;
    repeat
    inc(head);
    head:=(head-1) mod 205+1;
    u:=team[head];fl[u]:=false;
    for i:=1 to a[u,0] do
    if pd(u) then
    if dis[a[u,i]]>dis[u]+w[u,a[u,i]] then
    begin
    dis[a[u,i]]:=dis[u]+w[u,a[u,i]];
    pre[a[u,i]]:=u;
    if fl[a[u,i]]=false then
    begin
    inc(tail);
    tail:=(tail-1) mod 205+1;
    team[tail]:=a[u,i];
    fl[a[u,i]]:=true;
    end;
    end;
    until head=tail;
    if dis[t]=maxlongint div 3 then
    begin
    writeln(-1);
    halt;
    end;
    writeln(dis[t]);
    close(input);
    close(output);
    end.

信息

ID
1794
难度
6
分类
搜索 | 图结构 | 最短路 点击显示
标签
递交数
2557
已通过
606
通过率
24%
被复制
17
上传者