/* 一個凸多邊形n<=10000,cut了m次,每一刀不相交 求邊數最多那塊的邊數
這題用錯誤的做法搞了很久,浪費大量時間,囧 然后洗澡時想到了可以通過每次找一個“最小的環”來做 類似: http://watashi.ws/blog/970/andrew-stankevich-3-solution/ zoj 2361 上面這題十分推薦!!! 上面那題是按照極角排序,不過這題可以按照點的編號排序即可
多邊形的頂點看成圖的頂點,多邊形的邊是邊,cut也看成邊(雙向的邊) 建好圖后,對每個點找它所在的環(可能多個) 比如現在已經有邊pre->now,那么就在now的鄰接邊中找第一個比pre小的點 (沒有的話,就最大那個) 這樣,走出的環就是最小的了(也即環內沒有邊) 畫個圖就清楚了 8 4 2 8 2 4 4 6 6 8 */ #include<iostream> #include<cstring> #include<map> #include<algorithm> #include<stack> #include<queue> #include<cstring> #include<cmath> #include<string> #include<cstdlib> #include<vector> #include<cstdio> #include<set> #include<list> #include<numeric> #include<cassert> #include<sstream> #include<ctime> #include<bitset> #include<functional>
using namespace std;
const int INF = 0x3f3f3f3f; const int MAXN = 10086;
vector<int> e[MAXN];
int main() { #ifndef ONLINE_JUDGE freopen("in.txt","r",stdin); #endif
for (int N, M; ~scanf("%d%d", &N, &M); ) { for (int i = 1; i <= N; i++) { e[i].clear(); e[i].push_back(i == N ? 1 : i+1); //e[i].push_back(i == 1 ? N : i-1);這條邊不用加 } int x, y; for (int i = 0; i < M; i++) { scanf("%d%d", &x, &y); if (x > y) swap(x, y); //雙向的邊 e[x].push_back(y); e[y].push_back(x); } for (int i = 1; i <= N; i++) { sort(e[i].begin(), e[i].end()); } int ans = 0; for( int i = 1; i <= N; i++) { //cout<<endl<<i<<": \n"; for (vector<int>::iterator it = e[i].begin(), jt; it != e[i].end(); ) { int pre = i, now = *it, len = 1; //每次在now中尋找第一個小于pre的,這樣就是最小的環了,類似極角最小 while (now != i) { //cout<<pre<<" "<<now<<endl; len ++; jt = lower_bound(e[now].begin(), e[now].end(), pre); //不能寫成--jt < e[now].begin(),因為--jt不再屬于e[now]的范圍了 if (jt == e[now].begin()) { jt = --e[now].end(); } else jt --; pre = now; now = *jt; e[pre].erase(jt); } it = e[i].erase(it); //cout<<len<<endl; ans = max(ans, len); } } printf("%d\n", ans); } return 0; }
|
|
常用鏈接
隨筆分類
Links
搜索
最新評論

|
|