【思維題】【二分圖】TopCoder 12316 —— ThreeColorability
雖然這道題標籤有個二分圖,實際上只是用來判斷解的.此題的精髓應該是思維的過程
首先利用樣例 (題解),觀察出2*2的格子中,如果有解,那麼解一定為四個一樣或者各兩個的情況.不可能存在三個與一個的情況.也就是說,如果其中三條對角線的方向已經確定了,那麼第四條的方向也是確定的.
將上述的性質轉換為式子就是 .其中cells表示當前格子的狀態,0表示N,1表示Z
然後利用異或的性質可以推廣到任意一個矩形上.即如果有解則圖中任意一個矩形都滿足這個式子.
這樣就發現,在有解的條件,任意兩行的狀態要麼是相同的,要麼是相反的.
那麼就下來的事情都簡單了,因為上述的性質,我們可以將所有的約束條件壓到一行裡處理.掃描所有行的每一個位置,如果兩個位置的值不一樣,則連上邊.反之則用並查集維護狀態相同的.這樣處理過後,如果最後存在解,那麼這將是個二分圖,所以利用二分圖染色進行判定即可.
如果有解,那麼可以在染色的時候利用一點貪心的性質,讓0的狀態儘可能在前面.染色完畢後就得到了第一行的狀態.之後行的狀態可以利用當前行和第一行的關係,貪心地推出解.因為已經判斷出了此時是有解的,所以這樣做一定是可以找到解得.
(code by lwc)
#include <bits/stdc++.h>
using namespace std;
class ThreeColorability
{
static const int MAXN = 50 + 5;
class
{
int fa[ThreeColorability::MAXN];
public:
void initialize()
{
iota(fa, fa + ThreeColorability::MAXN, 0);
}
int find(int x)
{
if (fa[x] == x)
return x;
return fa[x] = find(fa[x]);
}
void merge(int x, int y)
{
// cerr << "Merge " << x << " " << y << endl ;
fa[find(x)] = find(y);
}
} disjointSet;
struct edge;
typedef struct edge * pEdge;
struct edge
{
int to;
pEdge nxt;
} E[MAXN * MAXN * 4];
int eCnt;
int N, M;
int vis[MAXN];
int a[MAXN][MAXN];
bool adjMat[MAXN][MAXN];
pEdge head[MAXN];
void addEdge(int u, int v)
{
// cerr << "Edge added :" << u << " " << v << endl ;
pEdge p;
p = &E[eCnt++];
p->nxt = head[u], head[u] = p;
p->to = v;
p = &E[eCnt++];
p->nxt = head[v], head[v] = p;
p->to = u;
}
bool isBipartite = true;
void DFS(int x, int col)
{
if (vis[x] >= 0)
{
// cerr << "Revisited " << x << " " << col << " " << vis[x] << endl ;
if (vis[x] != col)
isBipartite = false;
return;
}
vis[x] = col;
for (pEdge p = head[x]; p; p = p->nxt)
DFS(p->to, col ^ 1);
}
public:
ThreeColorability()
{
eCnt = 0;
N = 0, M = 0;
memset(vis, 0xFF, sizeof vis);
memset(head, 0x00, sizeof head);
memset(adjMat, 0x00, sizeof adjMat);
disjointSet.initialize();
}
vector<string> lexSmallest(vector<string> cells)
{
vector<string> answer = cells;
N = cells.size(), M = cells[0].length();
for (int i = 0; i < N; i++)
for (int j = 0; j < M; j++)
switch (cells[i][j])
{
case '?':
a[i][j] = -1;
break;
case 'N':
a[i][j] = 0;
break;
default:
a[i][j] = 1;
}
for (int i = 1; i < N; i++)
for (int j = 0; j < M; j++)
for (int k = j + 1; k < M; k++)
if ((~a[i][j]) && (~a[i][k]))
{
if (a[i][j] ^ a[i][k])
adjMat[j][k] = adjMat[k][j] = 1;
else
disjointSet.merge(j, k);
}
for (int i = 0; i < M; i++)
for (int j = i + 1; j < M; j++)
if (adjMat[i][j])
addEdge(disjointSet.find(i), disjointSet.find(j));
for (int i = 0; i < M; i++)
if (~a[0][i])
DFS(disjointSet.find(i), a[0][i]);
for (int i = 0; i < M; i++)
if (vis[disjointSet.find(i)] < 0)
DFS(disjointSet.find(i), 0);
if (!isBipartite)
return vector<string>
{ };
for (int i = 0; i < M; i++)
a[0][i] = vis[disjointSet.find(i)];
for (int i = 1; i < N; i++)
{
bool vist[2] =
{ 0 };
for (int j = 0; j < M; j++)
if (~a[i][j])
vist[a[i][j] ^ a[0][j]] = 1;
if (!vist[0] && !vist[1])
vist[a[0][0]] = 1;
if(vist[0])
for(int j = 0; j < M; j++)
a[i][j] = a[0][j];
else
for(int j = 0; j < M; j++)
a[i][j] = a[0][j] ^ 1;
}
for(int i = 0; i < N; i++)
for(int j = 0; j < M; j++)
answer[i][j] = (a[i][j] ? 'Z' : 'N');
return answer;
}
};
相關推薦
【思維題】【二分圖】TopCoder 12316 —— ThreeColorability
題目傳送門 雖然這道題標籤有個二分圖,實際上只是用來判斷解的.此題的精髓應該是思維的過程 首先利用樣例 (題解),觀察出2*2的格子中,如果有解,那麼解一定為四個一樣或者各兩個的情況.不可能存在三個與一個的情況.也就是說,如果其中三條對角線的方向已經確定了,那麼
【圖論】【思維題】AGC004F Namori
分析: 比較複雜的一道思維題。。。 先考慮樹的情況,把所有點按照深度的奇偶性分為兩類,在所有深度為奇的點放一個“+1”,在所有深度為偶的點放一個“-1”。這樣一來,每次染色,就可以看作交換了一對相鄰的“+1”和“-1”。目標狀態就是所有的“+1”移動到“-1”所
【二分圖】洛谷P1640連續攻擊遊戲
接下來 真的是 str style 並且 一行 include can div 題目描述 lxhgww最近迷上了一款遊戲,在遊戲裏,他擁有很多的裝備,每種裝備都有2個屬性,這些屬性的值用[1,10000]之間的數表示。當他使用某種裝備時,他只能使用該裝備的某一個屬性。並且每
【二分圖】ZJOI2007小Q的遊戲
格子 scan clas ecn 輸出 每次 他還 顏色 sed 660. [ZJOI2007] 小Q的矩陣遊戲 ★☆ 輸入文件:qmatrix.in 輸出文件:qmatrix.out 簡單對比 時間限制:1 s 內存限制:128 MB 【問題描述】
UVa 679 - Dropping Balls【二叉樹】【思維題】
get title lld -s round () color 直接 2個 題目鏈接 題目大意: 小球從一棵所有葉子深度相同的二叉樹的頂點開始向下落,樹開始所有節點都為0。若小球落到節點為0的則往左落,否則向右落。並且小球會改變它經過的節點,0變1,1變0。給定樹的深度
【二分圖】二分圖的多重匹配
pat 元素 () pre AI find main 尋找 ++ 某些問題中,會遇到一對多的二分圖模型,即允許集合Y中的一個元素和集合X中的多個元素匹配(通常有一個最大限制n) /*二分圖多重匹配算法*/ const int MAXN=1001;//最大頂點數 i
jzo5934. 【NOIP2018模擬10.29】列隊(二分圖匹配)
5934. 【NOIP2018模擬10.29】列隊 Description Sylvia是一個熱愛學習的女孩子。 在平時的練習中,他總是能考到std以上的成績,前段時間,他參加了一場練習賽,眾所周知,機房是一個 的方陣。這天,他又打爆了std,感到十分無聊,便想要hack機房內同學的
【思維題 kmp 構造】bzoj4974: [Lydsy1708月賽]字串大師
字串思博題這一塊還是有點薄弱啊。 Description 一個串T是S的迴圈節,當且僅當存在正整數k,使得S是T^k(即T重複k次)的字首,比如abcd是abcdabcdab的迴圈節 。給定一個長度為n的僅由小寫字元構成的字串S,請對於每個k(1<=k<=n
CodeForces 1072C Cram Time【思維題】
傳送門:http://codeforces.com/problemset/problem/1072/C C. Cram Time time limit per test 1 second memory limit per test 256 megabytes input
HDU 1045 Fire Net 【連通塊的壓縮 二分圖匹配】
題目:http://acm.hdu.edu.cn/showproblem.php?pid=1045 Fire Net Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Jav
BZOJ1345 Baltic2007 序列問題Sequence 【思維題】*
BZOJ1345 Baltic2007 序列問題Sequence Description 對於一個給定的序列a1,…,an,我們對它進行一個操作reduce(i),該操作將數列中的元素ai和ai+1用一個元素max(ai,ai+1)替代,這樣得到一個
【二分圖】【建圖】bzoj1059 矩陣遊戲
行列作為點 行為左部 列為右部 黑色格點表示從左部向右部連邊 使左上角到右下角的連線上的格子均為黑色 一個行只能和一個列連邊 相當於匹配 顯然每種完美匹配對應了一個方案 並不需要考慮如何調換和調換行列後方陣是什麼樣的 從而降低時間複雜度 #include
【BZOJ】4025: 二分圖
題解 lct維護一個結束時間作為邊權的最大生成樹,每次出現奇環就找其中權值最小的那條邊,刪掉的同時還要把它標記上,直到這條邊消失 如果有標記則輸出No 邊權通過建立虛點來維護 程式碼 #include <bits/stdc++.h> #define fi first #define se
【網路流/二分圖】Gym
題意: 有m個插座,n個電器,每個插座最多可連線一個電器。另外有一個插頭,可以使得一個插座連線三個電器,問最大匹配數是多少。 題解: 我是寫的網路流,先跑一遍容量都為1的dinic,然後列舉插座多給兩個容量,在殘餘網路中跑。每一次的列舉都需要把上一次的流量退回,可以
【思維題】【貪心】【模擬】【CodeForces】794 C Naming Company
【題意】 兩個人A和B在玩一個填字母遊戲。現在A和B都有一個包含 n 個小寫字母的多重集合(可以有重複字元)。 初始有一個長度為n的空字串s,兩人輪流操作,A先手。一次操作可以將自己集合中的一個字母拿出來,放到字串s的某個空位置,然後把這個字母從自己集合中刪除(如果
【二分圖】【找最大流、最小獨立集、匈牙利演算法】
Asteroids Bessie wants to navigate her spaceship through a dangerous asteroid field in the shape of an N x N grid (1
【離線 線段樹分治】bzoj4025: 二分圖
昨天mac的gdb掛了,今天怎麼筆記本的gdb也掛了…… Description 神犇有一個n個節點的圖。因為神犇是神犇,所以在T時間內一些邊會出現後消失。神犇要求出每一時間段內這個圖是否是二分圖。這麼簡單的問題神犇當然會做了,於是他想考考你。 Input 輸
BZOJ 1854: [Scoi2010]遊戲 【二分圖】【並查集】
Description lxhgww最近迷上了一款遊戲,在遊戲裡,他擁有很多的裝備,每種裝備都有2個屬性,這些屬性的值用[1,10000]之間的數表示。當他使用某種裝備時,他只能使用該裝備的某一個屬性。並且每種裝備最多隻能使用一次。 遊戲進行到最後,lxhgw
bzoj1854【二分圖】
第一次做的時候居然沒看出來二分圖。。一直想資料結構。。。中毒太深。。#include <cstdio> #include <cstring> #include <iostr
hdu 2063 過山車【二分圖】
題目連結 思路:二分圖匹配 匈牙利演算法(個人理解最優匹配):每次查詢都儘可能匹配,如果這個點的物件已經被匹配了,那就遞迴拆邊,遞迴這個過程保證拆後的點都能匹配才能夠回溯,否則不匹配,開始下一個