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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

[codevs 1922] 骑士共存问题

發(fā)布時(shí)間:2025/3/15 编程问答 17 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [codevs 1922] 骑士共存问题 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

[codevs 1922] 騎士共存問題


題解:

二分圖最大獨(dú)立集問題。


二分圖的最大獨(dú)立集:

選出一些點(diǎn),讓兩兩之間沒有邊相連。


二分圖最大獨(dú)立集問題一般轉(zhuǎn)化為它的對(duì)偶問題——最小覆蓋集,因?yàn)樽畲螵?dú)立集要求每條邊所連接的兩個(gè)點(diǎn)最多有一個(gè)被選中,而最小覆蓋集要求每條邊所連接的兩個(gè)點(diǎn)最少有一個(gè)被選中。那么點(diǎn)的個(gè)數(shù)-最小覆蓋集點(diǎn)的個(gè)數(shù)=最大獨(dú)立集(顯然減掉的越少剩下的越多)。


那么最小覆蓋怎么求呢?答案就是建立二分圖求最大基數(shù)匹配。可以簡(jiǎn)單證明一下:

1)充分性:如果還有一條邊沒有被覆蓋,那么此時(shí)一定可以把這條邊作為一條新的匹配,說明此時(shí)還不是最大匹配。

2)必要性:如果可以刪去一條邊,二分圖匹配邊中是沒有交點(diǎn)的,那么刪去后這條邊一定不會(huì)被覆蓋。


算法就到此結(jié)束。


原題中記得要把總點(diǎn)數(shù)減去不能走的格子數(shù)。


代碼:

dinic算法過了,ISAP死活不對(duì)...應(yīng)該是我寫的問題。

Dinic:

總時(shí)間耗費(fèi): 3172ms ?

總內(nèi)存耗費(fèi): 11 kB

#include<cstdio> #include<iostream> #include<vector> #include<cstring> #include<string> #include<queue> #include<algorithm> using namespace std;const int maxn = 200 * 200 + 10; const int INF = 1e9 + 7;const int dx[] = {-1, -2, -2, -1, 1, 2, 2, 1}; const int dy[] = {-2, -1, 1, 2, 2, 1, -1, -2};int n, m, s, t;struct Edge {int from, to, cap, flow; };vector<Edge> edges; vector<int> G[maxn];void AddEdge(int from, int to, int cap) {edges.push_back((Edge){from, to, cap, 0});edges.push_back((Edge){to, from, 0, 0});int sz = edges.size();G[from].push_back(sz-2);G[to].push_back(sz-1); }int id[222][222]; void init() {cin >> n >> m;s = 0; t = n*n - m + 1;for(int i = 0; i < m; i++) {int x, y;cin >> x >> y;id[x][y] = -1;}int c = 0;for(int i = 1; i <= n; i++)for(int j = 1; j <= n; j++)if(!id[i][j]) id[i][j] = ++c;for(int x = 1; x <= n; x++)for(int y = 1; y <= n; y++) if(id[x][y] > 0) {int ID = id[x][y];if((x+y)%2 == 0) {AddEdge(s, ID, 1);for(int i = 0; i < 8; i++) {int newx = x + dx[i], newy = y + dy[i];int newID = id[newx][newy];if(newx <= n && newy <= n && newx >= 1 && newy >= 1 && newID > 0) AddEdge(ID, newID, INF);}} else {AddEdge(ID, t, 1);}} }bool vis[maxn]; int d[maxn]; bool BFS() {queue<int> Q;Q.push(s);memset(vis, 0, sizeof(vis));d[s] = 0;vis[s] = 1;while(!Q.empty()) {int u = Q.front(); Q.pop();for(int i = 0; i < G[u].size(); i++) {Edge& e = edges[G[u][i]];if(!vis[e.to] && e.cap > e.flow) {vis[e.to] = 1;d[e.to] = d[u] + 1;Q.push(e.to);}}}return vis[t]; }int cur[maxn];int DFS(int u, int a) {if(a == 0 || u == t) return a;int f, flow = 0;for(int& i = cur[u]; i < G[u].size(); i++) {Edge& e = edges[G[u][i]];if(d[u] + 1 == d[e.to] && (f = DFS(e.to, min(a, e.cap-e.flow))) > 0) {flow += f;e.flow += f;a -= f;edges[G[u][i]^1].flow -= f;if(a == 0) break;}}return flow; }void Dinic() {int flow = 0;while(BFS()) {memset(cur, 0, sizeof(cur));flow += DFS(s, INF);}cout << n*n-m-flow << endl; }int main() {init();Dinic();return 0; }


ISAP:

TLE(哪錯(cuò)了呢?)

#include<cstdio> #include<iostream> #include<vector> #include<queue> #include<algorithm> using namespace std;const int maxn = 200 * 200 + 10; const int INF = 1e9 + 7;const int dx[] = {-1, -2, -2, -1, 1, 2, 2, 1}; const int dy[] = {-2, -1, 1, 2, 2, 1, -1, -2};int n, m, s, t;struct Edge {int from, to, cap, flow; };vector<Edge> edges; vector<int> G[maxn];void AddEdge(int from, int to, int cap) {edges.push_back((Edge){from, to, cap, 0});edges.push_back((Edge){to, from, 0, 0});int sz = edges.size();G[from].push_back(sz-2);G[to].push_back(sz-1); }int id[222][222]; void init() {cin >> n >> m;s = 0; t = n*n - m + 1;for(int i = 0; i < m; i++) {int x, y;cin >> x >> y;id[x][y] = -1;}int c = 0;for(int i = 1; i <= n; i++)for(int j = 1; j <= n; j++)if(!id[i][j]) id[i][j] = ++c;for(int x = 1; x <= n; x++)for(int y = 1; y <= n; y++) if(id[x][y] > 0) {int ID = id[x][y];if((x+y)%2 == 0) {AddEdge(s, ID, 1);for(int i = 0; i < 8; i++) {int newx = x + dx[i], newy = y + dy[i];int newID = id[newx][newy];if(newx <= n && newy <= n && newx >= 1 && newy >= 1 && newID > 0) AddEdge(ID, newID, INF);}} else {AddEdge(ID, t, 1);}} }bool vis[maxn]; int d[maxn], p[maxn], cur[maxn], num[maxn];int Augment() {int x = t, a = INF;while(x != 1) {Edge& e = edges[p[x]];a = min(a, e.cap-e.flow);x = e.from;}x = t;while(x != 1) {edges[p[x]].flow += a;edges[p[x]^1].flow -= a;x = edges[p[x]].from;}return a; }void BFS() {queue<int> Q;bool vis[maxn];memset(vis, 0, sizeof(vis));d[t] = 0;Q.push(t);while(!Q.empty()) {int x = Q.front(); Q.pop();for(int i = 0; i < G[x].size(); i++) {Edge& e = edges[G[x][i]];if(e.cap == 0 && !vis[e.to]) {d[e.to] = d[x] + 1;vis[e.to] = 1;Q.push(e.to);}}} } void Maxflow() {int flow = 0;BFS();memset(num, 0, sizeof(num));for(int i = 0; i <= t; i++) num[d[i]]++;int x = s;memset(cur, 0, sizeof(cur));while(d[s] < t) {if(x == t) {flow += Augment();x = s;}int ok = 0;for(int i = cur[x]; i < G[x].size(); i++) {Edge& e = edges[G[x][i]];if(e.cap > e.flow && d[x] == d[e.to] + 1) {ok = 1;p[e.to] = G[x][i];cur[x] = i;x = e.to;break;}}if(!ok) {int _m = t - 1;for(int i = 0; i < G[x].size(); i++) {Edge& e = edges[G[x][i]];if(e.cap > e.flow) _m = min(_m, d[e.to]);}if(--num[d[x]] == 0) break;num[d[x] = _m+1]++;cur[x] = 0;if(x != s) x = edges[p[x]].from;}}cout << n*n-m-flow << endl; }int main() {init();Maxflow();return 0; }我的ISAP連草地排水都WA一個(gè)點(diǎn)。。。


dinic算法過了,ISAP死活不對(duì)...應(yīng)該是我寫的問題。 TLE

總結(jié)

以上是生活随笔為你收集整理的[codevs 1922] 骑士共存问题的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

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