日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

POJ 图算法(3)

發(fā)布時間:2025/7/14 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 POJ 图算法(3) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

圖算法

度限制最小生成樹和第K最短路,分?jǐn)?shù)規(guī)劃

poj1639, poj3621, poj2976

poj2449poj3255poj2513

最短路,最小生成樹,二分圖,最大流問題的相關(guān)理論

poj3155,poj2112,poj1966,poj3281,poj1087,poj2289,poj3216,poj2446

最優(yōu)比率生成樹

poj27280/1分?jǐn)?shù)規(guī)劃應(yīng)用)

最小樹形圖

poj3164(-劉算法)

次小生成樹

poj1679(存在O(n^2)DP解法)

2-SAT問題

poj3207, poj3678, poj3683,poj3648, poj2723, poj2749

無向圖、有向圖的最小環(huán)

poj1734(floyd擴展)

?

?

?

?

?

?

?

?

?

?

?

?

?

度限制最小生成樹和第K最短路,分?jǐn)?shù)規(guī)劃 ?

?

?

poj 1639

標(biāo)準(zhǔn)的最小度限制生成樹,詳見:http://www.cnblogs.com/vongang/archive/2012/07/03/2575383.html

?

poj? 2976

很裸的分?jǐn)?shù)規(guī)劃,給n個數(shù)對,a[i],b[i]可以從中刪掉k個數(shù)對,然后使得sum(a)/sum(b)最大。

很經(jīng)典的分?jǐn)?shù)規(guī)劃問題。k = a(x)/b(x),轉(zhuǎn)化成a(x) - k*b(x),對a(x) - k*b(x)進行排序,刪掉前k小的數(shù),然后求和。

當(dāng)求和為0時說明得到方程的解。

?

View Code #include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <ctime> #include <queue> #include <map>#define CL(arr, val) memset(arr, val, sizeof(arr)) #define REP(i, n) for((i) = 0; (i) < (n); ++(i)) #define FOR(i, l, h) for((i) = (l); (i) <= (h); ++(i)) #define FORD(i, h, l) for((i) = (h); (i) >= (l); --(i)) #define L(x) (x) << 1 #define R(x) (x) << 1 | 1 #define MID(l, r) (l + r) >> 1 #define Min(x, y) x < y ? x : y #define Max(x, y) x < y ? y : x #define E(x) (1 << (x))const double eps = 1e-8; typedef long long LL; using namespace std;const int N = (1<<10);double f[N], g[N]; double G[N]; int dbcmp(double x) {if(x > eps) return 1;else if(x < -eps) return -1;return 0; }int main() {//freopen("data.in", "r", stdin);int n, k, i;while(~scanf("%d%d", &n, &k)) {if(n + k == 0) break;REP(i, n) scanf("%lf", f + i);REP(i, n) scanf("%lf", g + i);double sum, l = 0, r = 1;while(dbcmp(r - l) > 0) {double m = (l + r)/2;REP(i, n) G[i] = f[i] - g[i]*m;sort(G, G + n);for(sum = 0, i = k; i < n; ++i) sum += G[i];if(dbcmp(sum) > 0) l = m;else r = m;}printf("%d\n", int(r*100 + 0.5));}return 0; }

?

?poj 3621

題意:給一個無向圖,找到一個環(huán),使得環(huán)上的 點權(quán)之和/邊權(quán)之和 最大。

思路:這個還真不好想到。。。看的題解。sum(f[i])/sum(g[i][j]) == ans; 展開變形:

g[1][2]* ans - f[1] + g[2][3]*ans + f[2] + ... = 0;

這樣就可以把g[i][j]*ans - f[i]當(dāng)成一條邊的另一個權(quán)值。二分ans的值,如果有一個環(huán)按這個權(quán)值計算出現(xiàn)負(fù)環(huán),那么說明g[1][2]* ans - f[1] + g[2][3]*ans + f[2] + ... < 0 顯然ans要增加,反之減少。

注意g[i][j]*ans - f[i] 是double類型,在這里wa了好幾次。。。。

ans的上限定為1000就行。

View Code #include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <ctime> #include <queue> #include <map>#define CL(arr, val) memset(arr, val, sizeof(arr)) #define REP(i, n) for((i) = 0; (i) < (n); ++(i)) #define FOR(i, l, h) for((i) = (l); (i) <= (h); ++(i)) #define FORD(i, h, l) for((i) = (h); (i) >= (l); --(i)) #define L(x) (x) << 1 #define R(x) (x) << 1 | 1 #define MID(l, r) (l + r) >> 1 #define Min(x, y) x < y ? x : y #define Max(x, y) x < y ? y : x #define E(x) (1 << (x))const double eps = 1e-4; typedef long long LL; using namespace std;const int N = 1024; const double inf = ~0u>>1;struct node {int from;int to;int val;int next; } g[5100];int head[N], t; int cnt[N], f[N]; double dis[N]; bool inq[N]; int q[1000000];int n, m;void add(int u, int v, int w) {g[t].from = u; g[t].to = v; g[t].val = w;g[t].next = head[u]; head[u] = t++; }int dbcmp(double x) {if(x > eps) return 1;else if(x < -eps) return -1;return 0; }bool spfa(double ans) {int u, v, i;double w;int l = 0, r = 0;for(i = 1; i <= n; ++i) {dis[i] = inf; cnt[i] = 0; inq[i] = false;}q[r++] = 1; dis[1] = 0;inq[1] = true; cnt[1]++;while(l < r) {u = q[l++];for(i = head[u]; i != -1; i = g[i].next) {v = g[i].to; w = g[i].val*ans - f[g[i].from];if(dis[v] > dis[u] + w) {dis[v] = dis[u] + w;if(!inq[v]) {cnt[v] ++ ;if(cnt[v] > n) return false;inq[v] = true;q[r++] = v;}}}inq[u] = false;}return true; }int main() {//freopen("data.in", "r", stdin);int i, x, y, z;while(~scanf("%d%d", &n, &m)) {CL(head, -1); t = 0;CL(f, 0);FOR(i, 1, n) scanf("%d", f + i);FOR(i, 1, m) {scanf("%d%d%d", &x, &y, &z);add(x, y, z);}double l = 0, r = 100, mid;while(dbcmp(r - l) > 0) {mid = (l + r)/2;if(spfa(mid)) r = mid;else l = mid;}printf("%.2f\n", r);}return 0; }

?

poj 2449

裸第k短路:表示沒有接觸過A*,看論文看的眼冒金星。啟發(fā)函數(shù)好神奇。。。。

詳見:http://www.cnblogs.com/vongang/archive/2012/07/17/2594737.html

可以作為這類問題的模板

View Code #include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <ctime> #include <queue> #include <map> #include <sstream>#define CL(arr, val) memset(arr, val, sizeof(arr)) #define REP(i, n) for((i) = 0; (i) < (n); ++(i)) #define FOR(i, l, h) for((i) = (l); (i) <= (h); ++(i)) #define FORD(i, h, l) for((i) = (h); (i) >= (l); --(i)) #define L(x) (x) << 1 #define R(x) (x) << 1 | 1 #define MID(l, r) (l + r) >> 1 #define Min(x, y) x < y ? x : y #define Max(x, y) x < y ? y : x #define E(x) (1 << (x))const double eps = 1e-4; typedef long long LL; using namespace std;const int N = 1024; const int M = 100010; const int inf = ~0u>>2;struct edg {int to;int val;int next;edg() {}edg(int a, int b, int c): to(a), val(b), next(c) {} } g[M<<1], rg[M<<1];struct node {int f, g, v;node() {}node(int a, int b, int c) : f(a), g(b), v(c) {}bool operator < (const node& x) const {return x.f < f;} };int inq[N]; int head[N]; int rhead[N]; int dis[N]; int t, k;void init() {CL(head, -1);CL(rhead, -1);CL(inq, 0);t = 0;for(int i = 0; i < N; ++i) dis[i] = inf; }void add(int u, int v, int w) {g[t] = edg(v, w, head[u]);rg[t] = edg(u, w, rhead[v]);head[u] = t;rhead[v] = t++; }void spfa(int ed) {int i, u, v, w;queue<int> q;q.push(ed);inq[ed] = 1;dis[ed] = 0;while(!q.empty()) {u = q.front();for(i = rhead[u]; i != -1; i = rg[i].next) {v = rg[i].to; w = rg[i].val;if(dis[v] > dis[u] + w) {dis[v] = dis[u] + w;if(!inq[v]) { inq[v] = 1; q.push(v);}}}inq[u] = 0; q.pop();} }int A_star(int st, int ed) {priority_queue<node> Q;if(dis[st] == inf) return -1;int v, w;CL(inq, 0);Q.push(node(dis[st], 0, st));while(!Q.empty()) {node cur = Q.top();Q.pop(); inq[cur.v] ++;if(inq[ed] == k) return cur.f;if(inq[cur.v] > k) continue;for(int i = head[cur.v]; i != -1; i = g[i].next) {v = g[i].to; w = g[i].val;node New(dis[v] + cur.g + w, cur.g + w, v);Q.push(New);}}return -1; }int main() {//freopen("data.in", "r", stdin);int n, m, i;int u, v, w;int st, ed;init();scanf("%d%d", &n, &m);for(i = 0; i < m; ++i) {scanf("%d%d%d", &u, &v, &w);add(u, v, w);}scanf("%d%d%d", &st, &ed, &k);spfa(ed);if(st == ed) k++;printf("%d\n", A_star(st, ed));return 0; }

?

POJ 3255

題意是求1到n的次短路

改改模板就可以了,不過這里是無向圖,要加雙向邊的。。。

View Code #include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <ctime> #include <queue> #include <map> #include <sstream>#define CL(arr, val) memset(arr, val, sizeof(arr)) #define REP(i, n) for((i) = 0; (i) < (n); ++(i)) #define FOR(i, l, h) for((i) = (l); (i) <= (h); ++(i)) #define FORD(i, h, l) for((i) = (h); (i) >= (l); --(i)) #define L(x) (x) << 1 #define R(x) (x) << 1 | 1 #define MID(l, r) (l + r) >> 1 #define Min(x, y) x < y ? x : y #define Max(x, y) x < y ? y : x #define E(x) (1 << (x))const double eps = 1e-4; typedef long long LL; using namespace std;const int N = 5024; const int M = 100010; const int inf = ~0u>>2;struct edg {int to;int val;int next;edg() {}edg(int a, int b, int c): to(a), val(b), next(c) {} } g[M<<1], rg[M<<1];struct node {int f, g, v;node() {}node(int a, int b, int c) : f(a), g(b), v(c) {}bool operator < (const node& x) const {return x.f < f;} };int inq[N]; int head[N]; int rhead[N]; int dis[N]; int t, k;void init() {CL(head, -1);CL(rhead, -1);CL(inq, 0);t = 0;for(int i = 0; i < N; ++i) dis[i] = inf; }void add(int u, int v, int w) {g[t] = edg(v, w, head[u]);rg[t] = edg(u, w, rhead[v]);head[u] = t;rhead[v] = t++;g[t] = edg(u, w, head[v]);rg[t] = edg(v, w, rhead[u]);head[v] = t;rhead[u] = t++; }void spfa(int ed) {int i, u, v, w;queue<int> q;q.push(ed);inq[ed] = 1;dis[ed] = 0;while(!q.empty()) {u = q.front();for(i = rhead[u]; i != -1; i = rg[i].next) {v = rg[i].to; w = rg[i].val;if(dis[v] > dis[u] + w) {dis[v] = dis[u] + w;if(!inq[v]) { inq[v] = 1; q.push(v);}}}inq[u] = 0; q.pop();} }int A_star(int st, int ed) {priority_queue<node> Q;if(dis[st] == inf) return -1;int v, w;CL(inq, 0);Q.push(node(dis[st], 0, st));while(!Q.empty()) {node cur = Q.top();Q.pop(); inq[cur.v] ++;if(inq[ed] == k) return cur.f;if(inq[cur.v] > k) continue;for(int i = head[cur.v]; i != -1; i = g[i].next) {v = g[i].to; w = g[i].val;node New(dis[v] + cur.g + w, cur.g + w, v);Q.push(New);}}return -1; }int main() {//freopen("data.in", "r", stdin);int n, m, i;int u, v, w;int st, ed;init();scanf("%d%d", &n, &m);for(i = 0; i < m; ++i) {scanf("%d%d%d", &u, &v, &w);add(u, v, w);}st = 1; ed = n; k = 2;spfa(ed);if(st == ed) k++;printf("%d\n", A_star(st, ed));return 0; }

?

最優(yōu)比率生成樹

POJ 2728

一個典故:2005年杭州賽區(qū)。。。樓教高速AC此題,打亂了賽場節(jié)奏,順利奪冠。。。

最優(yōu)比例生成樹模板題,詳見:http://www.cnblogs.com/vongang/archive/2012/07/17/2596441.html

?

最小樹形圖?

POJ 3164 && HDU 2121

http://www.cnblogs.com/vongang/archive/2012/07/18/2596851.html

次小生成樹?

POJ 1679

http://www.cnblogs.com/vongang/archive/2012/07/18/2597739.html

?

2-SAT問題?

POJ 2-SAT六題 :http://www.cnblogs.com/vongang/archive/2012/02/16/2353770.html?

?

無向圖、有向圖的最小環(huán)?

POJ 1734

http://www.cnblogs.com/vongang/archive/2012/07/18/2598167.html

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

總結(jié)

以上是生活随笔為你收集整理的POJ 图算法(3)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。