「NOIP模拟赛」交通
黄金大神国的首都位于hzwer河中的一座岛屿。一道上班的时候,成千上万辆汽车通过岛屿从西岸的住宅区(由桥连接岛的西部)到东岸的工业区(由桥连接岛的东部)。
该岛类似于矩形,它的边平行于主方向。故可将它看作是笛卡尔坐标系中的一个A*B的矩形,它的对角分别为(0, 0)和(A, B)。
岛上有n个交通节点(后宫建筑),编号为1…n,第i个节点坐标为(xi, yi)。如果一个节点的坐标为(0, y),它就位于岛的西岸。类似的,坐标为(A, y)的节点位于岛的东岸。各个节点由街道连接,每条街道用线段连接两个节点。街道有单向行驶或双向行驶之分。除端点外任意两条街道都没有公共点。也没有桥梁或者隧道。
你不能对道路网络形状做任何其他假设。沿河岸的街道或节点可能没有入口或者出口街道。由于交通堵塞日趋严重,黄金大神想快速治理好他的国家,于是聘请你测试岛上当前的道路网是否足够。要求你写一个程序确定从岛的西岸的每个节点能够到达东岸的多少个节点。
「输入格式」
第1行包含4个整数n, m, A, B,分别表示hzwer市中心的节点数,街道数和岛屿的尺寸。
接下来的n行,每行包含两个整数xi,yi (0≤xi≤A,0≤yi≤B),表示第i个节点的坐标。任意两个节点的坐标都不相同。
再往下的m行表示街道,每条街道用3个整数ci, di, ki(1≤ci, di≤n, ci≠di, ki∈{1,2}),表示节点ci、di有街道连接,如果ki=1,表示从ci到di的街道是单向的,否则,这条街道可以双向行驶。每个无序对{ci, di}最多出现1次。
你可以假设西岸节点中至少有1个能够到达东岸的一些节点。
「输出格式」
为每个西岸节点输出1行,表示这个节点出发能够到达东岸的节点数目
「样例输入」
12 13 7 9
0 1
0 3
2 2
5 2
7 1
7 4
7 6
7 7
3 5
0 5
0 9
3 9
1 3 2
3 2 1
3 4 1
4 5 1
5 6 1
9 3 1
9 4 1
9 7 1
9 12 2
10 9 1
11 12 1
12 8 1
12 10 1
「样例输出」
4
4
0
2
「数据范围」
对于30%的数据,n, m≤6000
对于100%的数据,1≤n≤300000, 0≤m≤900000,1≤A,B≤10^9
题解
由于太弱想不出正解。。。
缩点后暴力可得70左右
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> #include<queue> #include<set> #include<map> #define pa pair<int,int> #define inf 1000000000 #define ll long long using namespace std; inline ll read() { ll x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int vis[300005]; int ans,n,m,A,B,cnt,cnt2,ind,top,scc; int dfn[300005],low[300005],q[300005],belong[300005]; int f[300005],r[300005]; bool inq[300005]; struct data{int x,y,id;}a[300005]; struct edge{int to,next;}e[1800005],ed[300005]; int last[300005],last2[300005]; void ins(int u,int v) { e[++cnt].to=v;e[cnt].next=last[u];last[u]=cnt; } void insert(int u,int v) { ed[++cnt].to=v;ed[cnt].next=last2[u];last2[u]=cnt; } void tarjan(int x) { dfn[x]=low[x]=++ind; q[++top]=x;inq[x]=1; for(int i=last[x];i;i=e[i].next) if(!dfn[e[i].to]) tarjan(e[i].to),low[x]=min(low[x],low[e[i].to]); else if(inq[e[i].to])low[x]=min(low[x],dfn[e[i].to]); int now=0; if(dfn[x]==low[x]) { scc++; while(now!=x) { now=q[top--];inq[now]=0; belong[now]=scc; if(a[now].x==A)f[scc]++; } } } void rebuild() { cnt=0; for(int x=1;x<=n+1;x++) for(int i=last[x];i;i=e[i].next) if(belong[x]!=belong[e[i].to]) insert(belong[x],belong[e[i].to]); } void dfs(int x) { if(vis[x])return;vis[x]=1;ans+=f[x]; for(int i=last2[x];i;i=ed[i].next) dfs(ed[i].to); } inline bool operator<(data a,data b) { return a.y>b.y; } int main() { //freopen("traffic.in","r",stdin); //freopen("traffic.out","w",stdout); n=read();m=read();A=read();B=read(); for(int i=1;i<=n;i++) { a[i].x=read(),a[i].y=read(),a[i].id=i; } for(int i=1;i<=m;i++) { int u=read(),v=read(),f=read(); if(f==1)ins(u,v); else ins(u,v),ins(v,u); } for(int i=1;i<=n;i++)if(!dfn[i])tarjan(i); rebuild(); int t[300005]; for(int i=1;i<=scc;i++)t[i]=f[i]; sort(a+1,a+n+1); for(int i=1;i<=n;i++) if(!a[i].x) { ans=0; for(int j=1;j<=scc;j++)f[j]=t[j],vis[j]=0; dfs(belong[a[i].id]); printf("%d\n",ans); } return 0; } |