【問題背景】
zhx 和他的妹子(們) 做遊戲。
【問題描述】
考慮 n 個人玩乙個遊戲,任意兩個人之間進行一場遊戲(共 n*(n-1)/2 場),
且每場一定能分出勝負。
現在, 你需要在其中找到三個人構成「剪刀石頭步」局面: 三個人 a, b, c
滿足 a 戰勝 b, b 戰勝 c, c 戰勝 a。
【輸入格式】
第一行乙個正整數 n, 表示參加遊戲的人數。
接下來 n 行, 每行 n 個數 0/1,中間沒有空格隔開。第 i 行第 j 列數字為 1
表示 i 在遊戲中戰勝了 j。 所有對角線元素(即第 i 行第 i 個元素) 為 0, 保證數
據合法。
【輸出格式】
如果存在三個人構成「剪刀石頭布」局面, 輸出三個人的編號(從 1 開始)。
如果不存在這樣的三個人, 輸出乙個數-1。
【樣例輸入】
500100
10000
01001
11101
11000
【樣例輸出】
1 3 2
【資料規模與約定】
分析:今天才知道這種圖叫競賽圖,還是第一次接觸它.
首先,競賽圖中是沒有兩元環的,兩個點不可能互指.並且競賽圖中一條任意長度的環都可以通過某種變換變成3元環,也就是題目要求的.具體是怎麼變換呢?考慮這樣乙個環:
考慮前3個點1、2、3,如果1、3之間的連邊是從3指向1,那麼就找到了乙個3元環,否則,我們完全可以不考慮2這個點,繼續考慮1,3,4,檢查1,4的連邊,這就和1,2,3這種情況一樣了,每次把環的長度-1,由於不存在2元環,所以最後一定可以找到乙個三元環.
接下來的任務就是怎麼要找到乙個任意長度的環.
把dfs走的圖看作一棵「樹」,如果子節點有邊連向祖先,那麼就形成了環.將dfs時的vis陣列改一下就可以了,vis[i] = 0表示i沒有訪問過,i=1表示正在訪問i或者i的子樹,i=2表示i的子樹訪問完了.如果下乙個點vis=1,那麼就找到乙個環了.維護乙個棧,記錄乙個時間戳,訪問到新節點就加入到棧中,子樹訪問完了就退出來,找到環後就把棧中對應下標的元素一複製就好了.
乙個比較重要的思想是把其它的所有不滿足條件的情況都給排除掉,一步步接近我們的目標.就好比找3元環,首先證明2元環是不存在的,然後證明大於3元環的一定可以找到3元環,把問題一步步縮小就能找到答案.
#include #include#include
#include
#include
#include
using
namespace
std;
int n, a[5010][5010], dfs_clock, s[5010], time[5010], head[5010], to[5010 * 5010], nextt[5010 * 5010], tot = 1
;int vis[5010], top, ans[5010
], cnt;
bool flag = false
;void add(int x, int
y)void dfs(int
u) }
vis[u] = 2
; s[top--] = 0;}
intmain()
for (int i = 1; i <= n; i++)
if (!vis[i])
if (!flag)
printf("-1
");else
}return0;
}
noip模擬賽 密碼
表示沒看懂演算法3 問題描述 有壓迫,就有反抗。mored的寵物在法庭的幫助下終於反抗了。作為乙隻聰明的寵物,他打算把魔法使mored的魔法書盜去,奪取mored的魔法能力。但mored怎麼會讓自己的魔法書輕易地被盜取?mored在魔法書上設定了乙個密碼鎖,密碼鎖上有乙個問題。施以斯臥鋪魔法吧,你有...
NOIP模擬賽 老師
題目描述 一座有n層的教學樓裡有一些學生,第i 0 i n 層有studentsi個學生。你被給定了乙個數k,如果第i層有x個學生,那麼這一層需要 x k 個老師。你可以調整每個學生的樓層,但是每個學生至多只能調整一層,就是說第i層的學生只能去第i 1層 如果有的話 第i層 第i 1層 如果i 1 ...
NOIP模擬賽 分錢
題目描述 兩個人在街上撿到了一些錢,這些錢共有n張,他們等了很久也沒有等來失主,於是決定把錢平分。但錢可能無法平分。他們先把能夠平分的錢盡量先平分了,使得剩下不能平分的錢盡量少。這些不能平分的錢怎麼辦呢他?他們決定拿去賭場裡面賭一把。他們運氣太好了,那些不能平分的錢變成了雙倍,於是他們就把那個錢分了...