《挑战程序设计竞赛》2.5 它们其实都是图
来源:互联网 发布:秦柯 python 编辑:程序博客网 时间:2024/05/18 03:46
POJ - 2139 Six Degrees of Cowvin Bacon(裸floyd)
题意:N头牛,拍了M部电影,同一部电影中的搭档们距离1,求最小度数之和。
#include <cstdio>#include <queue>#include <cstring>#include <algorithm>#include <iostream>using namespace std;const int mod = 1e9;const int maxn_e = 10005;const int maxn_v = 300 + 5;const int INF = 0x3f3f3f3f;//用LL的时候要修改int d[maxn_v][maxn_v];int a[maxn_v];void init(int V){ for(int i = 1; i <= V; i++) { for(int j = 1;j <= V; j++) { d[i][j] = (i == j) ? 0 : INF; } }}void Floyd(int V){ for(int k = 1;k <= V; k++) { for(int i = 1; i <= V; i++) { for(int j = 1; j <= V; j++) { d[i][j] = min(d[i][j], d[i][k] + d[k][j]);//看情况加不加 判断 INF d[i][k] d[k][j] } } }}int main(){ int V, M; scanf("%d%d", &V, &M); init(V); //输入数据并建图 for(int i = 0; i < M; i++) { int n, t; scanf("%d", &n); for(int j = 0; j < n; j++) { scanf("%d", &a[j]); } for(int j = 0; j < n; j++) { for(int k = 0; k < j; k++) { d[ a[j] ][ a[k] ] = d[ a[k] ][ a[j] ] = 1; } } } Floyd(V); int minn = INF; for(int i = 1; i <= V; i++) { int tot = 0; for(int j = 1; j <= V; j++) { if(i == j) continue; tot += d[i][j]; } minn = min(minn, 100 * tot / (V - 1)); } cout << minn << endl; return 0;}
POJ - 3259 Wormholes(判负环)
题意:
虫洞问题,现在有n个点,m条边,代表现在可以走的通路,比如从a到b和从b到a需要花费c时间,现在在地上出现了w个虫洞,虫洞的意义就是你从a到b话费的时间是-c(时间倒流,并且虫洞是单向的),现在问你能不能从某个点开始走,回到从前。即找负环。
思路:
言下之意就是判断有无负环,bellman或者spfa一套模板就行了。
#include <cstdio>#include <vector>#include <queue>#include <cstring>using namespace std;int n, m, w;const int maxv = 500+5;const int INF = 0x3f3f3f3f;int vis[maxv],cnt[maxv],dis[maxv];struct edge{ int to, co; edge(int tt, int cc):to(tt), co(cc){}};vector<edge>G[maxv];void ma_init(){ scanf("%d%d%d", &n, &m, &w); for(int i = 1; i <= n; i++)//vector要记得重置 G[i].clear(); int s, e, t; for(int i = 0; i < m; i++) { scanf("%d%d%d", &s, &e, &t); G[s].push_back({e, t});//因为这个边是双向的,所以两边都要压进去。 G[e].push_back({s, t}); } for(int i = 0; i < w; i++) { scanf("%d%d%d", &s, &e, &t); G[s].push_back({e, -t});//虫洞是单向的 且是负值 }}bool spfa(int s){ memset(vis, 0, sizeof(vis)); memset(cnt, 0, sizeof(cnt)); for(int i = 1; i <= n; i++) dis[i] = INF;//初始化distant数组 //进队之前的初始化 queue<int>que; dis[s] = 0; que.push(s); vis[s] = cnt[s] = 1;//vis数组表示 s结点在队列中 cnt数组表示 s结点入队一次 while(!que.empty()) { int v = que.front();que.pop();//取出队列中队首的顶点的编号v vis[v] = 0;//弹出之后消除标记 for(int i = 0; i < G[v].size(); i++)//对顶点v的所有相连的边进行一次遍历。 { edge e = G[v][i]; if(dis[e.to] > dis[v] + e.co)//进行更新 { dis[e.to] = dis[v] + e.co; if(vis[e.to] == 0)//若顶点e.to此时不在队列中,则压进队中,并更新一系列数据 { que.push(e.to); vis[e.to] = 1; cnt[e.to]++; if(cnt[e.to] > n) return false;//如果有一个顶点进队了n次,则存在负环 } } } } return true;}int main(){ int T; scanf("%d",&T); while(T--) { ma_init(); if(!spfa(1) || dis[1]<0 ) printf("YES\n"); else printf("NO\n"); } return 0;}
POJ - 3268 Silver Cow Party(spfa or dijkstra)
题意:
给出n个点和m条边,接着是m条边,代表从牛a到牛b需要花费c时间,现在所有牛要到牛x那里去参加聚会,并且所有牛参加聚会后还要回来,给你牛x,除了牛x之外的牛,他们都有一个参加聚会并且回来的最短时间,从这些最短时间里找出一个最大值输出。
思路:
回家的时候不用说,一个裸的最短路问题。去聚会的问题稍微转换一下,是不是等价于把所有的边反向以后,从牛x家求一个最短路。
#include <cstdio>#include <vector>#include <queue>#include <algorithm>using namespace std;const int maxv = 1000+5;const int INF = 0x3f3f3f3f;typedef pair<int, int>pii;int dis[maxv], vis[maxv], tot[maxv];struct edge{ int to, co; edge(int tt, int cc):to(tt), co(cc){}};vector<edge>G1[maxv];vector<edge>G2[maxv];void init(int V){ for(int i = 1; i <= V; i++) { G1[i].clear(); G2[i].clear(); }}void dijkstra(int s, int V, vector<edge>G[]){ for(int i = 0; i <= V; i++) dis[i] = INF; //通过指定greater<P>参数,堆按照first从小到大的顺序取出值。 priority_queue<pii, vector<pii>, greater<pii> >que; dis[s] = 0; que.push({0, s}); while(!que.empty()) { pii p = que.top();que.pop(); int v = p.second, d = p.first; if(d > dis[v]) continue;//剪枝:比最短路还大,没有更新的意义 for(int i = 0; i < G[v].size(); i++) { edge &e = G[v][i];//因为会有修改,所以取引用。 if(dis[e.to] > dis[v] + e.co) { dis[e.to] = dis[v] + e.co; que.push({dis[e.to], e.to}); } } } for(int i = 1; i <= V; i++) tot[i] += dis[i];}int main(){ int n, m, x; scanf("%d%d%d", &n, &m, &x);//一共有n只牛,m条路,在x牛处举行party init(n); for(int i = 0; i < m; i++) { int u, v, w; scanf("%d%d%d", &u, &v, &w); G1[u].push_back({v, w}); G2[v].push_back({u, w}); } dijkstra(x, n, G1); dijkstra(x, n, G2); int ans = *max_element(tot, tot + 1 + n); printf("%d\n", ans); return 0;}
POJ - 1258 Agri-Net(最小生成树裸题)
题意:
有n个农场,已知这n个农场都互相相通,有一定的距离,现在每个农场需要装光纤,问怎么安装光纤能将所有农场都连通起来,并且要使光纤距离最小,输出安装光纤的总距离。
思路:
这题特么是多case的我擦。。#include <cstdio>#include <queue>#include <cstring>#include <algorithm>#include <iostream>using namespace std;const int mod = 1e9;const int maxn = 100 + 5;int ma[maxn][maxn];typedef pair<int, int>pii;struct edge{ int u, v, w; bool operator < (const edge &other) const { return w < other.w; }}edges[maxn * maxn];int pa[maxn];void init(int n){ for(int i = 0; i <= n; i++) pa[i] = i;}int uf_find(int x){ return pa[x] == x ? x : (pa[x] = uf_find(pa[x]));}bool same(int x,int y){return (uf_find(x) == uf_find(y)) ? true : false;}void join(int x, int y){ int fx = uf_find(x), fy = uf_find(y); if(fx != fy) pa[fx] = fy;}int kruskal(int vs, int es){ int ret = 0; sort(edges, edges + es); init(vs); for(int i = 0; i < es; i++) { edge e = edges[i]; if(!same(e.v, e.u)) { ret += e.w; join(e.v, e.u); } } return ret;}int main(){ int n; while(~scanf("%d", &n)) { int cnt = 0; for(int i = 1; i <= n; i++) { for(int j = 1; j <= n; j++) { int x; scanf("%d", &x); if(i == j) continue; edges[cnt].v = i, edges[cnt].u = j, edges[cnt].w = x; cnt++; } } cout << kruskal(n, cnt) << endl; } return 0;}
POJ - 2377 Bad Cowtractors(最大生成树)
题意:
坏奶牛:为了破坏农夫约翰的光纤计划,奶牛决定骗丫拉一条最长的网络。
思路:
最小变最大。。
wa点:要判一下有没有孤点
#include <cstdio>#include <queue>#include <cstring>#include <algorithm>#include <iostream>using namespace std;const int mod = 1e9;const int maxn = 100 + 5;typedef pair<int, int>pii;//最大生成树struct edge{ int u, v, w; bool operator < (const edge &other) const { return w > other.w; }}edges[20000 + 5];int pa[1000 + 5];void init(int n){ for(int i = 0; i <= n; i++) pa[i] = i;}int uf_find(int x){ return pa[x] == x ? x : (pa[x] = uf_find(pa[x]));}bool same(int x,int y){return (uf_find(x) == uf_find(y)) ? true : false;}void join(int x, int y){ int fx = uf_find(x), fy = uf_find(y); if(fx != fy) pa[fx] = fy;}int kruskal(int vs, int es){//最大生成树 还要判断一个悬浮孤点 init(vs); sort(edges, edges + es); int ret = 0; int cnt_num = 1; for(int i = 0; i < es; i++) { edge e = edges[i]; if(!same(e.v, e.u)) { ret += e.w; join(e.v, e.u); cnt_num++; } } if(cnt_num < vs) return -1; return ret;}int main(){ int vs, es; scanf("%d%d", &vs, &es); for(int i = 0; i < es; i++) { scanf("%d%d%d", &edges[i].u, &edges[i].v, &edges[i].w); } cout << kruskal(vs, es) << endl; return 0;}
POJ - 2395 Out of Hay(最小生成树)
题意:
求干草:奶牛没草吃了,要去附近的农场找,求最短遍历路径上最长的那条路。
思路:
还要提示咩。#include <cstdio>#include <queue>#include <cstring>#include <algorithm>#include <iostream>using namespace std;const int mod = 1e9;const int maxn = 100 + 5;const int INF = 0x3f3f3f3f;typedef pair<int, int>pii;struct edge{ int u, v, w; bool operator < (const edge &other) const { return w < other.w; }}edges[10000 + 5];int pa[2000 + 5];void init(int n){ for(int i = 0; i <= n; i++) pa[i] = i;}int uf_find(int x){ return pa[x] == x ? x : (pa[x] = uf_find(pa[x]));}bool same(int x,int y){return (uf_find(x) == uf_find(y)) ? true : false;}void join(int x, int y){ int fx = uf_find(x), fy = uf_find(y); if(fx != fy) pa[fx] = fy;}int kruskal(int vs, int es){ init(vs); sort(edges, edges + es); int ret = 0; int maxedge = -INF; for(int i = 0; i < es; i++) { edge e = edges[i]; if(!same(e.v, e.u)) { ret += e.w; join(e.v, e.u); maxedge = max(maxedge, e.w); } } cout << maxedge << endl; return ret;}int main(){ int vs, es; scanf("%d%d", &vs, &es); for(int i = 0; i < es; i++) { scanf("%d%d%d", &edges[i].u, &edges[i].v, &edges[i].w); } kruskal(vs, es); return 0;}
0 0
- 《挑战程序设计竞赛》2.5 它们其实都是图
- 二分图(挑战程序设计竞赛)
- 二分图判定 (挑战程序设计竞赛)
- 《挑战程序设计竞赛》 读后感
- 挑战程序设计竞赛:三角形
- 《挑战程序设计竞赛》 读后感
- 挑战程序设计竞赛(1)
- 2.5其实他们都是“图”
- 挑战程序设计竞赛p42(贪心)
- ACM Ball(挑战程序设计竞赛)
- ACM Hopscotch(挑战程序设计竞赛)
- ACM Osenbei(挑战程序设计竞赛)
- ACM Packets(挑战程序设计竞赛)
- 挑战程序设计竞赛---POJ.2686
- 挑战程序设计竞赛---POJ.3233
- 水洼 POJ2386 挑战程序设计竞赛
- 挑战程序设计竞赛:0101抽签
- 挑战程序设计竞赛笔记_P55
- Lintcode 主元素 III
- js实现继承的几种方式
- AndroidStudio创建项目时的minimum SDK作用
- POJ 2057 The Lost House 树型dp+贪心思想在动态规划上的应用
- 登录时session与用户
- 《挑战程序设计竞赛》2.5 它们其实都是图
- 代码片段整理
- c++第四次作业
- 用python快速将excel(含多sheet)导入MySQL(兼容中文)
- Android增量更新和签名校验
- easyui tabs 刷新当前页
- 开始我的学习之路~~~
- Linux进程间通信——使用信号
- 二叉排序树