【枚举】【SPFA】Urozero Autumn Training Camp 2016 Day 5: NWERC-2016 Problem I. Iron and Coal

那个人派出的队伍的行走的路径一定前半程是重合的,后半程分叉开来。

于是预处理每个点离1号点的最短路,到最近的铁的最短路,到最近的煤的最短路。(三次BFS / SPFA)然后枚举分岔点,尝试更新答案即可。

#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
queue<int>q;
int v[1000010],first[100010],next[1000010],en;
ll ans=2147483647ll;
void AddEdge(int U,int V){
	v[++en]=V;
	next[en]=first[U];
	first[U]=en;
}
int n,m,K,a[100010],b[100010],dis1[100010],dis2[100010],dis3[100010],eu[1000010],ev[1000010],es;
bool inq[100010];
void spfa1(int dis[])
{
	memset(dis,0x7f,sizeof(int)*100010);
	memset(inq,0,sizeof(inq));
	for(int i=1;i<=m;++i){
		dis[a[i]]=0;
		q.push(a[i]);
		inq[a[i]]=1;
	}
    while(!q.empty())
      {
        int U=q.front();
        for(int i=first[U];i;i=next[i])
          if(dis[v[i]]>dis[U]+1)
            {
              dis[v[i]]=dis[U]+1;
              if(!inq[v[i]])
                {
                  q.push(v[i]);
                  inq[v[i]]=1;
                }
            }
        q.pop(); inq[U]=0;
      }
}
void spfa2(int dis[])
{
	memset(dis,0x7f,sizeof(int)*100010);
	memset(inq,0,sizeof(inq));
	for(int i=1;i<=K;++i){
		dis[b[i]]=0;
		q.push(b[i]);
		inq[b[i]]=1;
	}
    while(!q.empty())
      {
        int U=q.front();
        for(int i=first[U];i;i=next[i])
          if(dis[v[i]]>dis[U]+1)
            {
              dis[v[i]]=dis[U]+1;
              if(!inq[v[i]])
                {
                  q.push(v[i]);
                  inq[v[i]]=1;
                }
            }
        q.pop(); inq[U]=0;
      }
}
void spfa3(int dis[]){
	memset(dis,0x7f,sizeof(int)*100010);
	memset(inq,0,sizeof(inq));
	dis[1]=0; q.push(1); inq[1]=1;
    while(!q.empty())
      {
        int U=q.front();
        for(int i=first[U];i;i=next[i])
          if(dis[v[i]]>dis[U]+1)
            {
              dis[v[i]]=dis[U]+1;
              if(!inq[v[i]])
                {
                  q.push(v[i]);
                  inq[v[i]]=1;
                }
            }
        q.pop(); inq[U]=0;
      }
}
int main(){
//	freopen("i.in","r",stdin);
	scanf("%d%d%d",&n,&m,&K);
	for(int i=1;i<=m;++i){
		scanf("%d",&a[i]);
	}
	for(int i=1;i<=K;++i){
		scanf("%d",&b[i]);
	}
	int x,y;
	for(int i=1;i<=n;++i){
		scanf("%d",&x);
		for(int j=1;j<=x;++j){
			scanf("%d",&y);
			AddEdge(y,i);
			eu[++es]=i;
			ev[es]=y;
		}
	}
	spfa1(dis1);
	spfa2(dis2);
	memset(first,0,sizeof(first));
	memset(next,0,sizeof(next));
	memset(v,0,sizeof(v));
	en=0;
	for(int i=1;i<=es;++i){
		AddEdge(eu[i],ev[i]);
	}
	spfa3(dis3);
	for(int i=1;i<=n;++i){
		ans=min(ans,(ll)dis3[i]+(ll)dis1[i]+(ll)dis2[i]);
	}
	if(ans<=2000000000ll){
		printf("%d\n",(int)ans);
	}
	else{
		puts("impossible");
	}
	return 0;
}
时间: 2024-10-17 23:32:15

【枚举】【SPFA】Urozero Autumn Training Camp 2016 Day 5: NWERC-2016 Problem I. Iron and Coal的相关文章

【计算几何】【预处理】【枚举】Urozero Autumn Training Camp 2016 Day 5: NWERC-2016 Problem K. Kiwi Trees

发现由于角的度数和边的长度有限制,那俩圆如果放得下的话,必然是塞在两个角里. 于是预处理n个圆心的位置(注意要判断那个圆会不会和其他的边界相交),然后n^2枚举俩角即可. #include<cstdio> #include<cmath> using namespace std; #define EPS 0.00000001 struct Point{ double x,y; double length(){ return sqrt(x*x+y*y); } }a[2010]; typ

【强连通分量缩点】【DFS】【动态规划】Urozero Autumn Training Camp 2016 Day 5: NWERC-2016 Problem B. British Menu

有向图,不经过重复点的最长链,强连通分量大小不超过5. 每个强连通分量内部暴力预处理任意两对点之间的最长路,外面DAG上dp. 不是很好写,但是预处理完了之后,可以重构每个强连通分量内部的结构,然后整个就变成一张DAG了,就很方便了. #include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <

【二分】Urozero Autumn Training Camp 2016 Day 5: NWERC-2016 Problem C. Careful Ascent

二分Vx即可. #include<cstdio> #include<algorithm> using namespace std; #define EPS 0.00000000001 struct RANGE{ int l,r; double f; }rs[110]; bool cmp(const RANGE &a,const RANGE &b){ return a.l<b.l; } int xe,ye,n,Left; bool check(double vx

湖南省第十三届大学生计算机程序设计竞赛 Football Training Camp 贪心

2007: Football Training Camp[原创-转载请说明] Submit Page   Summary   Time Limit: 1 Sec     Memory Limit: 128 Mb     Submitted: 228     Solved: 30 Description 在一次足球联合训练中一共有n支队伍相互进行了若干场比赛. 对于每场比赛,赢了的队伍得3分,输了的队伍不得分,如果为平局则两支队伍各得1分. Input 输入包含不超过1000组数据. 每组数据的第

Petrozavodsk Summer Training Camp 2017

Petrozavodsk Summer Training Camp 2017 Problem A. Connectivity 题目描述:有\(n\)个点,现不断地加边.每条边有一种颜色,如果一个点对\((a, b)\),满足\(a=b\)或对于每一种颜色的子图(图中只有该种颜色的边),\(a, b\)总是连通,则该点对称为好连通.求出每加一条边,好连通的点对数. solution 每个子图用并查集维护连通块,并且用\(vector\)记录每个连通块的点,便于之后进行答案的统计,合并时启发式合并即

2015 UESTC Winter Training #7【2010-2011 Petrozavodsk Winter Training Camp, Saratov State U Contest】

2015 UESTC Winter Training #7 2010-2011 Petrozavodsk Winter Training Camp, Saratov State U Contest 据说这套题写出3题就是金牌水平了... Problem D. Group Stage 足球比赛,现在有n(2<= n <=100)支球队.要从中选拔m(1<= m <=n-1)支球队,每支球队互相比赛一场,即比赛n*(n-1)/2场,胜者得3分,平局各得1分.最后从大到小列出排名,如果有

D. Marcin and Training Camp

题目链接:http://codeforces.com/contest/1230/problem/D D. Marcin and Training Camp time limit per test: 3 seconds memory limit per test: 256 megabytes input: standard input output: standard output 题目大意: 要组建一个小组,要求小组中每个人都不比所有人强,当一个人懂得一个算法但是另一个不懂那么前者认为他比后者强

D. Marcin and Training Camp ( Codeforces Round #588 (Div. 2) )

Marcin is a coach in his university. There are nn students who want to attend a training camp. Marcin is a smart coach, so he wants to send only the students that can work calmly with each other. Let's focus on the students. They are indexed with int

Codeforces Round #588 (Div. 2) D. Marcin and Training Camp(思维)

链接: https://codeforces.com/contest/1230/problem/D 题意: Marcin is a coach in his university. There are n students who want to attend a training camp. Marcin is a smart coach, so he wants to send only the students that can work calmly with each other. L