UVA 1516 Smoking gun 查分约束+拓扑
2015-09-16 10:49
417 查看
题意:给你几个人的位置,他们可能会开枪,再给你几组关系,A B C,代表A听到B在C之前开枪,问你能否确定他们的开枪顺序。
思路:对于一组关系A B C,可以得出以下公式:fb+tb <= fc+tc,fb代表b的开火时间,tb代表b从开火到声音传到A所需的时间,因为先听到b,所以用<=,移项可得一组不等式,建边,跑一边spfa判断是否有负环,如果没有,则拓扑排序,输出解即可。
这道题我交了能有十来遍,最后发现double下0x3f3f3f3f不能初始化T T,还是自己懂得太少了。。。
思路:对于一组关系A B C,可以得出以下公式:fb+tb <= fc+tc,fb代表b的开火时间,tb代表b从开火到声音传到A所需的时间,因为先听到b,所以用<=,移项可得一组不等式,建边,跑一边spfa判断是否有负环,如果没有,则拓扑排序,输出解即可。
这道题我交了能有十来遍,最后发现double下0x3f3f3f3f不能初始化T T,还是自己懂得太少了。。。
#include <cstdio> #include <iostream> #include <cstring> #include <algorithm> #include <queue> #include <vector> #include <cmath> #include <cstdlib> #include <string> #include <map> #include <set> using namespace std; const int maxn = 100 + 10; const int maxe = 2000 + 10; const double INF = 0x3f3f3f3f; const double eps = 1e-8; struct Edge{ int v; double d; int next; Edge(int v = 0, double d = 0, int next = 0) : v(v), d(d), next(next) {} }; struct Point{ double x, y; int id; Point(double x = 0, double y = 0, int id = 0) : x(x), y(y), id(id){} void read(int _id){ scanf("%lf%lf", &x, &y); id = _id; } }; int n, m, _size; int Head[maxn], cntE; int in[maxn]; double dist[maxn]; int cnt[maxn]; int vis[maxn]; int ans[maxn], t; set<int> member; map<string, Point> ma; map<int, string> ma2; vector<int> G[maxn]; Point p[maxn]; Edge edge[maxe]; int dcmp(double x){ if(fabs(x) < eps) return 0; return x < 0 ? -1 : 1; } void init(){ for(int i = 0; i < n; i++) G[i].clear(); memset(Head, -1, sizeof(Head)); memset(in, 0, sizeof(in)); cntE = 0; member.clear(); ma2.clear(); ma.clear(); } void add(int u, int v, double d){ edge[cntE] = Edge(v, d, Head[u]); Head[u] = cntE++; } double pow_2(double x){ return x * x; } double Dis_2(string str1, string str2){ return sqrt(pow_2(ma[str2].x - ma[str1].x) + pow_2(ma[str2].y - ma[str1].y)); } int spfa(int s){ for(int i = 0; i < n; i++) dist[i] = INF; memset(vis, 0, sizeof(vis)); memset(cnt, 0, sizeof(cnt)); dist[s] = 0; cnt[s] = 1; queue<int> Q; Q.push(s); while(!Q.empty()){ int u = Q.front(); Q.pop(); vis[u] = 0; for(int i = Head[u]; ~i; i = edge[i].next){ int v = edge[i].v; if(dist[v] > dist[u] + edge[i].d){ dist[v] = dist[u] + edge[i].d; if(!vis[v]){ vis[v] = 1; Q.push(v); if(++cnt[v] > _size) return -1; } } } } int f = 0; for(int i = 0; i < n; i++)if(dcmp(dist[i]) < 0){ G[i].push_back(s); in[s]++; f = 1; } return f; } void build(){ string str1, str2, str3, s; for(int i = 0; i < m; i++){ /*Andy heard BillyTheKid firing before John*/ cin >> str1 >> s >> str2 >> s >> s >> str3; int u = ma[str3].id; int v = ma[str2].id; double dis = Dis_2(str1, str3) - Dis_2(str1, str2); add(u, v, dis); member.insert(ma[str2].id); member.insert(ma[str3].id); } } void solve(){ cin >> n >> m; init(); string str1; for(int i = 0; i < n; i++){ cin >> str1; p[i].read(i); ma[str1] = p[i]; ma2[p[i].id] = str1; } build(); _size = (int)member.size(); for(int i = 0; i < n; i++){ int flag = spfa(i); if(flag < 0){ cout << "IMPOSSIBLE" << endl; return; } if(flag) member.erase(i); } t = 0; while((int)member.size()){ if((int)member.size() > 1){ cout << "UNKNOWN" << endl; return; } int cur = *member.begin(); member.erase(member.begin()); ans[t++] = cur; for(int i = 0; i < (int)G[cur].size(); i++){ --in[G[cur][i]]; if(!in[G[cur][i]]) member.insert(G[cur][i]); } } for(int i = 0; i < t; i++){ if(i) cout << " "; cout << ma2[ans[i]]; } cout << endl; } int main() { int T; cin >> T; while(T--) solve(); return 0; }
相关文章推荐
- SDUT 3320 GCD问题 莫比乌斯反演
- 【LeetCode】Maximum Depth of Binary Tree 解题报告
- perror打造linux C 编程开发中的错误定位与捕捉函数
- 使用方便git命令检查记录的版本号
- oracle中视图v$sql的用途
- JAVA里的String、Timestamp、Date相互转换(转)
- oracle安全管理
- public class 和 class的区别
- MPTCP 介绍
- android混淆和反编译
- android混淆和反编译
- android布局中更换控件顺序后无法正常运行的解决办法
- scala 安装和入门
- remastersys用法
- Jmeter压力测试工具
- chrome textension Content Security Policy
- android混淆和反编译
- Android(java)学习笔记258:JNI之hello.c(c代码功能实现)指针语法解析
- MyEclipse 8.5破解
- NSArray和NSMutableArray的创建及常用方法