码迷,mamicode.com
首页 > 其他好文 > 详细

洛谷 P2169 正则表达式

时间:2018-01-14 22:46:42      阅读:164      评论:0      收藏:0      [点我收藏+]

标签:需要   新建   输入输出格式   eof   网络连接   closed   描述   ++   就是   

题目背景

小Z童鞋一日意外的看到小X写了一个正则表达式的高级程序,这个正则表达式程序仅仅由字符“0”,“1”,“.”和“*”构成,但是他能够匹配出所有在OJ上都AC的程序的核心代码!小Z大为颇感好奇,于是他决定入侵小X的电脑上去获得这个正则表达式的高级程序。

题目描述

在Internet网络中的每台电脑并不是直接一对一连通的,而是某些电脑之间存在单向的网络连接,也就是说存在A到B的连接不一定存在B到A的连接,并且有些连接传输速度很快,有些则很慢,所以不同连接传输所花的时间是有大有小的。另外,如果存在A到B的连接的同时也存在B到A的连接的话,那么A和B实际上处于同一局域网内,可以通过本地传输,这样花费的传输时间为0。

现在小Z告诉你整个网络的构成情况,他希望知道从他的电脑(编号为1),到小X的电脑(编号为n)所需要的最短传输时间。

输入输出格式

输入格式:

 

第一行两个整数n, m, 表示有n台电脑,m个连接关系。

接下来m行,每行三个整数u,v,w;表示从电脑u到电脑v传输信息的时间为w。

 

输出格式:

 

输出文件仅一行为最短传输时间。

 

输入输出样例

输入样例#1: 复制
3 2
1 2 1
2 3 1
输出样例#1: 复制
2
输入样例#2: 复制
5 5
1 2 1
2 3 6
3 4 1
4 2 1
3 5 2
输出样例#2: 复制
3

说明

对于40%的数据,1<=n<=1000, 1<=m<=10000

对于70%的数据,1<=n<=5000, 1<=m<=100000

对于100%的数据,1<=n<=200000, 1<=m<=1000000

 

题目即求缩点后从1到达n的最短距离

缩点后并不需要重新建边,只需要在跑最短路时判断u,v两点是否在同一个强连通分量中。

若在同一个强联通分量中,那么直接将边权赋值为0。

技术分享图片
#include<complex>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int N=2e5+7;
struct node{
    int v,w,nxt;
}e[N*5];
int n,m,Enum,cnt,top;
int front[N],Low[N],Dfn[N],fat[N],dis[N],sk[N];
bool vis[N];
queue<int>q;
int qread()
{
    int x=0;
    char ch=getchar();
    while(ch<0 || ch>9)ch=getchar();
    while(ch>=0 && ch<=9){x=x*10+ch-0;ch=getchar();}
    return x;
}
void Insert(int u,int v,int w)
{
    e[++Enum].v=v;
    e[Enum].w=w;
    e[Enum].nxt=front[u];
    front[u]=Enum;
}
int find(int x)
{
    if(fat[x]!=x)fat[x]=find(fat[x]);
    return fat[x];
}
void Tarjan(int x)
{
    Low[x]=Dfn[x]=++cnt;
    vis[x]=1;
    sk[++top]=x;
    int v;
    for(int i=front[x];i;i=e[i].nxt)
    {
        v=e[i].v;
        if(!Dfn[v])
        {
            Tarjan(v);
            Low[x]=min(Low[x],Low[v]);
        }
        else
            if(vis[v])
                Low[x]=min(Low[x],Dfn[v]);
    }
    if(Low[x]==Dfn[x])
        do{
            fat[sk[top]]=x;
            vis[sk[top--]]=0;
        }while(sk[top+1]!=x);
}
void SPFA()
{
    memset(dis,0x3f,sizeof(dis));
    memset(vis,0,sizeof(vis));
    dis[1]=0;
    vis[1]=1;
    q.push(1);
    int u,v,r1,r2;
    while(!q.empty())
    {
        u=q.front();r1=find(u);
        q.pop();
        vis[u]=0;
        for(int i=front[u];i;i=e[i].nxt)
        {
            v=e[i].v;r2=find(v);
            if(r1==r2)e[i].w=0;
            if(dis[v]>dis[u]+e[i].w)
            {
                dis[v]=dis[u]+e[i].w;
                if(!vis[v])
                {
                    vis[v]=1;
                    q.push(v);
                }
            }
        }
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    int u,v,w;
    for(int i=1;i<=m;i++)
    {
        u=qread();v=qread();w=qread();
        Insert(u,v,w);
    }
    for(int i=1;i<=n;i++)
        if(!Dfn[i])
            Tarjan(i);
    SPFA();
    printf("%d\n",dis[n]);
    return 0;
}
View Code

 

洛谷 P2169 正则表达式

标签:需要   新建   输入输出格式   eof   网络连接   closed   描述   ++   就是   

原文地址:https://www.cnblogs.com/1078713946t/p/8284453.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!