HDU 4183 Pahom on Water(点双连通分量)
2015-09-10 21:38
411 查看
题意:有很多的被涂上颜色的呈圆形的垫子,一些垫子可以有相同的颜色,但是红色和紫罗兰只有一个,垫子摆放的时候可以相交,初始一个人站在红垫子上,这个人要从红垫子走到紫罗兰垫子,然后再从紫罗兰垫子走到红垫子,问你是否可以在满足以下条件完成上述的动作。
~rule1(red->violet):a垫子和b垫子相交(要有公共面积,点不算)P(a)<P(b);则可以从a走到b;
~rule2(violet->red):a垫子和b垫子相交(要有公共面积,点不算)P(a)>P(b);则可以从a走到b;
思路:
点双连通分量:分量内的任意一个点到其中的其它各点都有两条没有公共点的路径相通。
建图的时候不一定所有满足条件的边都要建,只要建与red_pad和violet_pad有关的边即可。
~rule1(red->violet):a垫子和b垫子相交(要有公共面积,点不算)P(a)<P(b);则可以从a走到b;
~rule2(violet->red):a垫子和b垫子相交(要有公共面积,点不算)P(a)>P(b);则可以从a走到b;
思路:
点双连通分量:分量内的任意一个点到其中的其它各点都有两条没有公共点的路径相通。
建图的时候不一定所有满足条件的边都要建,只要建与red_pad和violet_pad有关的边即可。
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<stack> using namespace std; const int pad_num=300+5; const int edge=305*305; int n; int red_id,vio_id; struct node { double fre; int x,y; int rad; }pad[pad_num]; struct nodee { int v,next; }e[edge]; int head[pad_num],cnt; int vis[pad_num]; void Init() { memset(head,-1,sizeof(head)); cnt=0; } void add(int a,int b) { e[cnt].v=b; e[cnt].next=head[a]; head[a]=cnt++; } int Input() { int red=0,vio=0; scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%lf %d %d %d",&pad[i].fre,&pad[i].x,&pad[i].y,&pad[i].rad); if(abs(pad[i].fre-400)<1e-8) { red_id=i;red=1; } if(abs(pad[i].fre-789)<1e-8) { vio_id=i;vio=1; } } if(red==0||vio==0) return 0; return 1; } double Dis(int x1,int y1,int x2,int y2) { return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)); } void dfs(int i) { vis[i]=1; for(int j=1;j<=n;++j) { if(i==j) continue; if(Dis(pad[i].x,pad[i].y,pad[j].x,pad[j].y)>(pad[i].rad+pad[j].rad)) continue; if(fabs(pad[j].fre-pad[i].fre)<1e-8) continue; if(pad[j].fre<pad[i].fre) continue; add(i,j); add(j,i); if(!vis[j]) dfs(j); } } void buildmap() { memset(vis,0,sizeof vis); dfs(red_id); } struct nnode { int f,t; }ee[pad_num]; int paint[pad_num],dfn[pad_num],low[pad_num],index,col; stack<nnode>s; void Init_tarjan() { memset(paint,0,sizeof(paint)); memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); index=col=1; while(!s.empty()) s.pop(); } int Min(int a,int b) { if(a<b) return a; return b; } void tarjan(int u,int f) { dfn[u]=low[u]=index++; for(int i=head[u];i+1;i=e[i].next) { int v=e[i].v; nnode w; w.f=u;w.t=v; if(!dfn[v]) { s.push(w); tarjan(v,u); low[u]=Min(low[u],low[v]); if(low[v]>=dfn[u]) { while(1) { nnode w=s.top(); s.pop(); paint[w.f]=col; paint[w.t]=col; if(w.f==u) break; } col++; } } else if(v!=f&&dfn[u]>dfn[v]) { low[u]=Min(low[u],dfn[v]); } } } void treatment() { Init_tarjan(); for(int i=1;i<=n;i++) { if(!dfn[i]) tarjan(i,-1); } if(paint[red_id]==paint[vio_id]&&paint[red_id]!=0) printf("Game is VALID\n"); else printf("Game is NOT VALID\n"); } int main() { int t; scanf("%d",&t); while(t--) { Init(); if(!Input()) { printf("Game is NOT VALID\n"); continue; } buildmap(); treatment(); } return 0; }
相关文章推荐
- Leet Code 11 Container With Most Water
- Effective C++ 条款38 通过复合塑模出has-a或"根据某物实现出"
- Rust - Unique pointers | 独一无二的指针(所有权指针)
- Hat's Fibonacci 1250 (大数+数学 好题)
- 设计模式——结构型模式
- iOS开发之 KVC,KVO简单了解
- 批判Rust语言,以及C/C++为什么永远不会死
- java笔记——初识面向对象04继承
- UVA - 1658(网络流经典拆点方法)
- vim修改二进制文件
- C#高級------数据字典练习
- MEMS惯性传感器
- 每日一“结”(3)
- HDU2546【01背包问题模板题】
- 数据分析师成长之路
- iOS实现带历史记录功能的计算器
- android中如何实现进入一个界面不做任何动作过10秒钟自动跳转到其他activity?
- Mysql:is not allowed to connect to this MySQL server
- LVM配置
- 设计模式(8):中介者模式