• codevs 1269 匈牙利游戏


    /*暴力+乱搞 55分(似乎只有暴力得分了)*/
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<algorithm>
    #define maxn 1000010
    using namespace std;
    int n,m,num,head[maxn],dfn[maxn],low[maxn],s[maxn],top,f[maxn];
    int sum,topt,c[maxn],dis[maxn],dis2[maxn],vis[maxn],pre[maxn];
    int belong[maxn],cir[maxn],ans1=0x7fffffff,ans2=0x7fffffff,D,falg;
    struct node
    {
        int u,v,t,pre;
    }e[maxn];
    void Add(int from,int to,int dis)
    {
        num++;
        e[num].u=from;
        e[num].v=to;
        e[num].t=dis;
        e[num].pre=head[from];
        head[from]=num;
    }
    void Tarjan(int x)
    {
        low[x]=dfn[x]=++topt;
        s[++top]=x;f[x]=1;
        for(int i=head[x];i;i=e[i].pre)
          if(dfn[e[i].v]==0){Tarjan(e[i].v);low[x]=min(low[x],low[e[i].v]);}
          else if(f[e[i].v]==1)low[x]=min(low[x],dfn[e[i].v]);
        if(low[x]==dfn[x])
          {
              sum++;
              while(x!=s[top])
                {
                    c[sum]++;f[s[top]]=0;
                belong[s[top]]=sum;top--;
              }
            c[sum]++;f[s[top]]=0;
            belong[s[top]]=sum;top--;
          }
    }
    void SPFA()
    {
        queue<int>q;
        memset(dis,127/3,sizeof(dis));
        memset(vis,0,sizeof(vis));
        dis[1]=0;vis[1]=1;q.push(1);
        while(!q.empty())
          {
              int k=q.front();q.pop();vis[k]=0;
              for(int i=head[k];i;i=e[i].pre)
                {
                    int v=e[i].v;
                    if(dis[v]>dis[k]+e[i].t)
                      {
                          dis[v]=dis[k]+e[i].t;pre[v]=k;
                          if(vis[v]==0){vis[v]=1;q.push(v);}
                  }
              }
          }
    }
    void SPFA2(int si,int ti)
    {
        queue<int>q;
        memset(dis2,127/3,sizeof(dis));
        memset(vis,0,sizeof(vis));
        dis2[1]=0;vis[1]=1;q.push(1);
        while(!q.empty())
          {
              int k=q.front();q.pop();vis[k]=0;
              for(int i=head[k];i;i=e[i].pre)
                {
                    int v=e[i].v;
                    if(si==k&&ti==v)continue;
                    if(dis2[v]>dis2[k]+e[i].t)
                      {
                          dis2[v]=dis2[k]+e[i].t;
                          if(vis[v]==0){vis[v]=1;q.push(v);}
                  }
              }
          }
    }
    void Dfs(int x,int d)
    {
        if(d>ans1)return;
        if(x==n&&d!=dis[n])
          {
              ans1=min(ans1,d);
              return;
          }
        for(int i=head[x];i;i=e[i].pre)
          Dfs(e[i].v,d+e[i].t);
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        int x,y,z;
        for(int i=1;i<=m;i++)
          {
              scanf("%d%d%d",&x,&y,&z);
              if(x==1&&y==n)
              D=z;
              Add(x,y,z);
          }
        for(int i=1;i<=n;i++)
          if(dfn[i]==0)Tarjan(i);
        for(int i=1;i<=n;i++)
          if(c[belong[i]]>=2)cir[i]=1;
        SPFA();
        int p=n;
        while(p>1)
          {
              if(cir[p]==1)falg=1;p=pre[p];
          }
        if(falg)
          {
              Dfs(1,0);
              if(ans1==0x7fffffff)printf("-1
    ");
            else printf("%d
    ",ans1);
              return 0;
          }
        p=n;
        while(p>1)
          {
              SPFA2(pre[p],p);
              if(dis2[n]!=dis[n])ans2=min(ans2,dis2[n]);
              if(cir[p]==1)ans1=min(ans1,dis[n]+c[belong[p]]);
              p=pre[p];
          }
        if(D!=dis[n])ans1=min(ans1,D);
        if(ans2==0x7fffffff&&sum==0)printf("-1
    ");
        else printf("%d
    ",min(ans1,ans2));
        return 0; 
    }
    /*
    正解. 正反跑spfa 记录每个节点的1跑过来的最短路和n跑过来的最短路
    考试的时候想的是每个点的这两个值加起来 然后求此小值 
    后来发现 样例都过不了.....
    原因是 这里的dis数组的定义决定了会忽略一些边
    所以 接着这个思路想下来 我们强制走某一条边
    也就是我们枚举边 然后计算 disu + dis2v + uv 就是一条路径的长度
    注意这里统计出来的数的个数不是路径数 因为同一条路径上的许多边都统计了一遍
    但这里求的是严格次短路 这就很好的符合我们求出来的值 只需要找出第二小的不同的就好
    也就是说 这种方法不能求次短路 
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<algorithm>
    #define maxn 200010
    using namespace std;
    int n,m,num,num2,head[maxn],head2[maxn],dis[maxn],dis2[maxn],vis[maxn],ans[maxn],l;
    int ans1=707406378,ans2=707406378;
    struct node
    {
        int u,v,t,pre;
    }e[maxn],e2[maxn];
    void Add(int from,int to,int dis)
    {
        num++;
        e[num].u=from;
        e[num].v=to;
        e[num].t=dis;
        e[num].pre=head[from];
        head[from]=num;
    }
    void Add2(int from,int to,int dis)
    {
        num2++;
        e2[num].u=from;
        e2[num].v=to;
        e2[num].t=dis;
        e2[num].pre=head2[from];
        head2[from]=num2;
    }
    void SPFA()
    {
        queue<int>q;
        memset(dis,127/3,sizeof(dis));
        memset(vis,0,sizeof(vis));
        dis[1]=0;vis[1]=1;q.push(1);
        while(!q.empty())
          {
              int k=q.front();q.pop();vis[k]=0;
              for(int i=head[k];i;i=e[i].pre)
                {
                    int v=e[i].v;
                    if(dis[v]>dis[k]+e[i].t)
                      {
                          dis[v]=dis[k]+e[i].t;
                          if(vis[v]==0){vis[v]=1;q.push(v);}
                  }
              }
          }
    }
    void SPFA2()
    {
        queue<int>q;
        memset(dis2,127/3,sizeof(dis));
        memset(vis,0,sizeof(vis));
        dis2[n]=0;vis[n]=1;q.push(n);
        while(!q.empty())
          {
              int k=q.front();q.pop();vis[k]=0;
              for(int i=head2[k];i;i=e2[i].pre)
                {
                    int v=e2[i].v;
                    if(dis2[v]>dis2[k]+e2[i].t)
                      {
                          dis2[v]=dis2[k]+e2[i].t;
                          if(vis[v]==0){vis[v]=1;q.push(v);}
                  }
              }
          }
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        int x,y,z;
        for(int i=1;i<=m;i++)
          {
              scanf("%d%d%d",&x,&y,&z);
              Add(x,y,z);Add2(y,x,z);
          }
        SPFA();SPFA2();
        for(int i=1;i<=num;i++)
          {
              int u=e[i].u;int v=e[i].v;
              ans[++l]=dis[u]+dis2[v]+e[i].t;
          }
        sort(ans+1,ans+1+l);
        ans1=ans[1];
        for(int i=2;;i++)
          if(ans[i]!=ans1)
            {
              ans2=ans[i];break;
            }
        if(ans2>=0x7fffffff)printf("-1
    ");
        else printf("%d
    ",ans2);
        return 0;
    }
  • 相关阅读:
    大话设计模式总结(28种设计模式定义+简单理解)
    Dbank网盘下载地址提取ASP
    C#特性详解
    wcf大文件传输解决之道(1)
    WCF完美搭建android平台服务之一
    堆栈和委托堆的区别(c#)一
    wcf完美搭建android平台服务之三
    liunx简单命令集合
    WCF完美搭建android平台服务之二
    WCF中常用的binding方式比较
  • 原文地址:https://www.cnblogs.com/yanlifneg/p/5741496.html
Copyright © 2020-2023  润新知