• 【洛谷P5590】赛车游戏


    题目

    题目链接:https://www.luogu.com.cn/problem/P5590
    双倍经验:https://codeforces.com/problemset/problem/241/E
    R 君和小伙伴打算一起玩赛车。但他们被老司机 mocania 骗去了秋名山。
    秋名山上有 (n) 个点和 (m) 条边,R 君和他的小伙伴要从点 (1) 出发开往点 (n),每条边都有一个初始的方向。老司机 mocania 拿到了秋名山的地图但却不知道每条路有多长。显然,为了赛车游戏的公平,每条 (1)(n) 的路径应当是等长的。mocania 想,我就随便给边表上一个 (1...9) 的长度,反正傻傻的 R 君也看不出来。
    可 mocania 的数学不大好,不知道怎么给边标长度,只能跑来请教你这个 OI 高手了。
    无解输出 -1
    (nleq 1000)(mleq 2000)

    思路

    差分约束板子题我都不会做了哈哈哈哈哈哈哈哈哈。
    需要注意的是如果一个点不在 (1)(n) 的路径上,那么这个点即使在负环内也无所谓。
    时间复杂度 (O(nm))

    代码

    #include <bits/stdc++.h>
    using namespace std;
    
    const int N=1010,M=4010,Inf=1e9;
    int n,m,tot,head[N],dis[N],cnt[N],flag[N];
    bool vis[N];
    
    struct edge
    {
    	int next,from,to,dis;
    }e[M];
    
    void add(int from,int to,int dis)
    {
    	e[++tot]=(edge){head[from],from,to,dis};
    	head[from]=tot;
    }
    
    bool spfa()
    {
    	memset(dis,0x3f,sizeof(dis));
    	queue<int> q;
    	q.push(1); dis[1]=0;
    	while (q.size())
    	{
    		int u=q.front(); q.pop();
    		vis[u]=0;
    		for (int i=head[u];~i;i=e[i].next)
    		{
    			int v=e[i].to;
    			if (flag[v]==2 && dis[v]>dis[u]+e[i].dis)
    			{
    				dis[v]=dis[u]+e[i].dis; cnt[v]=cnt[u]+1;
    				if (cnt[v]>n) return 0;
    				if (!vis[v]) { q.push(v); vis[v]=1; }
    			}
    		}
    	}
    	return 1;
    }
    
    void dfs(int x,int val)
    {
    	flag[x]++; vis[x]=1;
    	for (int i=head[x];~i;i=e[i].next)
    	{
    		int v=e[i].to;
    		if (!vis[v] && e[i].dis==val) dfs(v,val);
    	}
    }
    
    int main()
    {
    	memset(head,-1,sizeof(head));
    	scanf("%d%d",&n,&m);
    	for (int i=1,x,y;i<=m;i++)
    	{
    		scanf("%d%d",&x,&y);
    		add(x,y,9); add(y,x,-1);
    	}
    	dfs(1,9);
    	memset(vis,0,sizeof(vis));
    	dfs(n,-1);
    	memset(vis,0,sizeof(vis));
    	if (flag[1]<2) return printf("-1"),0;
    	if (!spfa()) return printf("-1"),0;
    	cout<<n<<" "<<m<<"
    ";
    	for (int i=1;i<=tot;i+=2)
    	{
    		int u=e[i].from,v=e[i].to;
    		if (flag[u]<2 || flag[v]<2) cout<<u<<" "<<v<<" 1
    ";
    			else cout<<u<<" "<<v<<" "<<dis[v]-dis[u]<<"
    ";
    	}
    	return 0;
    }
    
  • 相关阅读:
    spring集成quartz
    ScheduledExecutorService
    中国方言输入法Rime入门
    TinyOS实例介绍
    公式输入较好的参考
    USRP IQ信号分析
    法语学习(1)--入门资料推荐
    Python小技巧
    编码知识
    jaspersoft studio colunm header and detail ,detail中显示多列数据
  • 原文地址:https://www.cnblogs.com/stoorz/p/15419307.html
Copyright © 2020-2023  润新知