班長選挙-連通子図+縮点
38952 ワード
タイトルの説明
大学のクラスは班長を選んで、N人の学友はすべて意見を発表することができて、もし意見がA BならばAはBが適切だと思って、意見は伝達性があって、つまりAはBが適切だと思って、BはCが適切だと思って、AもCが適切で勤勉なTTはM条の意見を集めて、最高の票数を知りたくて、そして候補者のリストを出して、つまりすべての得票が最も多い学友、あなたは彼を助けることができますか?
Input
この問題には複数のデータがあります.1行目Tは、データ群数を表す.各セットのデータは、2つの整数NおよびM(2<=n<=5000、0
Output
各グループのデータに対して、1行目は「Case x:」、xはデータの番号を表し、1から、最も高い票数が続く.次の行は得票が最も多い学生の番号を出力して、スペースで隔てて、行末のスペースを無視しません!
Sample Input
2 4 3 3 2 2 0 2 1
3 3 1 0 2 1 0 2
Sample Output
Case 1: 2 0 1 Case 2: 2 0 1 2
問題を解く構想.
本題と前の問題では感覚が違うのは、簡単そうに見えるかもしれませんが、実際によく考えてみると解決するのは難しいことに気づきます.この問題を見たばかりの頃、まずFloydアルゴリズムを用いることを考えた.このアルゴリズムは伝達性の問題を解決できるからだが、リングが存在する可能性があるという問題を考慮して、説明の中でこの方法に言及していないことを考慮して、しばらく放棄するか、それとも標準アルゴリズムを用いるか.まずdfsを用いて遍歴し、0点から図の後序シーケンスを見つけ、それから逆後序シーケンスを見つけた.このシーケンスに基づいて逆図を巡回し、各連通サブ図を見つけ、対応するタグを付けます.連通サブマップに基づいて縮点を行い,縮点後の原図と反図を得,原図に出度0の縮点を見つけ,縮点後の反図にこれらの点を起点としてdfs遍歴を行い,縮点後の重み値に基づいて経路が最も長い縮点を見つけ,最後の求め値である.
コード#コード#
大学のクラスは班長を選んで、N人の学友はすべて意見を発表することができて、もし意見がA BならばAはBが適切だと思って、意見は伝達性があって、つまりAはBが適切だと思って、BはCが適切だと思って、AもCが適切で勤勉なTTはM条の意見を集めて、最高の票数を知りたくて、そして候補者のリストを出して、つまりすべての得票が最も多い学友、あなたは彼を助けることができますか?
Input
この問題には複数のデータがあります.1行目Tは、データ群数を表す.各セットのデータは、2つの整数NおよびM(2<=n<=5000、0
Output
各グループのデータに対して、1行目は「Case x:」、xはデータの番号を表し、1から、最も高い票数が続く.次の行は得票が最も多い学生の番号を出力して、スペースで隔てて、行末のスペースを無視しません!
Sample Input
2 4 3 3 2 2 0 2 1
3 3 1 0 2 1 0 2
Sample Output
Case 1: 2 0 1 Case 2: 2 0 1 2
問題を解く構想.
本題と前の問題では感覚が違うのは、簡単そうに見えるかもしれませんが、実際によく考えてみると解決するのは難しいことに気づきます.この問題を見たばかりの頃、まずFloydアルゴリズムを用いることを考えた.このアルゴリズムは伝達性の問題を解決できるからだが、リングが存在する可能性があるという問題を考慮して、説明の中でこの方法に言及していないことを考慮して、しばらく放棄するか、それとも標準アルゴリズムを用いるか.まずdfsを用いて遍歴し、0点から図の後序シーケンスを見つけ、それから逆後序シーケンスを見つけた.このシーケンスに基づいて逆図を巡回し、各連通サブ図を見つけ、対応するタグを付けます.連通サブマップに基づいて縮点を行い,縮点後の原図と反図を得,原図に出度0の縮点を見つけ,縮点後の反図にこれらの点を起点としてdfs遍歴を行い,縮点後の重み値に基づいて経路が最も長い縮点を見つけ,最後の求め値である.
コード#コード#
#include
#include
#include
#include
#include
#include
using namespace std;
const int maxm = 5010, maxn = 3e4 + 10;
int head1[maxm], head2[maxm], out_deg[maxm];//
int vis[maxm], c[maxm];//c scc ,vis
int scc[maxm], scnt;//scc ,scnt
int dfn[maxm], dcnt;//
int T, N, M, A, B;
int tot1 = 0, tot2 = 0;
int sh_vis[maxm];
int ans[maxm];
pair<int, int> a[maxm];//ans
struct Edge
{
int u, v, nxt;// , , ,
};
Edge e1[maxn], e2[maxn];//
vector<int> sh_gra1[maxm], sh_gra2[maxm];//
int temp = 0;
void addedge1(int u, int v)
{
e1[tot1].u = u;
e1[tot1].v = v;
out_deg[u]++;
e1[tot1].nxt = head1[u];
head1[u] = tot1;
tot1++;
}
void addedge2(int u, int v)
{
e2[tot2].u = u;
e2[tot2].v = v;
e2[tot2].nxt = head2[u];
head2[u] = tot2;
tot2++;
}
void init()
{
tot1 = tot2 = 0;
dcnt = scnt = 0;
temp = 0;
for (int i = 0; i <= N; i++)
{
a[i].first = a[i].second = 0;
head1[i] = -1;
head2[i] = -1;
out_deg[i] = 0;
vis[i] = 0;
scc[i] = 0;
c[i] = 0;
ans[i] = 0;
while (sh_gra1[i].size()) sh_gra1[i].pop_back();
while (sh_gra2[i].size()) sh_gra2[i].pop_back();
}
}
void dfs1(int m)
{
vis[m] = 1;
for (int i = head1[m]; i != -1; i = e1[i].nxt)
if (!vis[e1[i].v]) dfs1(e1[i].v);
dfn[dcnt] = m;
dcnt++;
}
void dfs2(int m)
{
c[m] = scnt;
scc[c[m]]++;//
for (int i = head2[m]; i != -1; i = e2[i].nxt)
if (!c[e2[i].v]) dfs2(e2[i].v);
}
void get_shorted_graph()
{
for (int i = 1; i <= N; i++)
out_deg[i] = 0;
for (int i = 0; i < N; i++)
for (int j = head1[i]; j != -1; j = e1[j].nxt)
{
int y = e1[j].v;
if (c[i] == c[y]) continue;
sh_gra1[c[i]].push_back(c[y]);
out_deg[c[i]]++;
sh_gra2[c[y]].push_back(c[i]);//
}
}
void dfs3(int m)
{
sh_vis[m] = 1;
for (auto i : sh_gra2[m])
{
if (!sh_vis[i])
{
ans[temp] += scc[i];
dfs3(i);
}
}
}
bool cmp(pair<int, int>a, pair<int, int>b)
{
return a.first > b.first;
}
int main()
{
std::ios::sync_with_stdio(false);
cin >> T;
for (int i = 0; i < T; i++)
{
cin >> N >> M;
init();
for (int j = 0; j < M; j++)
{
cin >> A >> B;
addedge1(A, B);
addedge2(B, A);//
}
for (int j = 0; j < N; j++)
if (!vis[j]) dfs1(j);
for (int j = dcnt - 1; j >= 0; j--)
if (!c[dfn[j]])
{
scnt++;
dfs2(dfn[j]);
}
get_shorted_graph(); //
vector<int> zero_outd;
for (int j = 1; j <= scnt; j++)
if (!out_deg[j]) zero_outd.push_back(j);
int s = zero_outd.size();
for (int j = 0; j < s; j++)
{
memset(sh_vis, 0, sizeof sh_vis);
ans[temp] += scc[zero_outd[j]] - 1;
dfs3(zero_outd[j]);
a[temp].first = ans[temp];
a[temp].second = zero_outd[j];
temp++;
}
while (zero_outd.size()) zero_outd.pop_back();
sort(a, a + s, cmp);
cout << "Case " << i + 1 << ": " << a[0].first << endl;
priority_queue<pair<int, int> > w;
pair<int, int> r;
int h = 0;
for (int j = 0; j < s; j++)
{
h = 0;
if (a[j].first == a[0].first)
{
for (int u = 0; u < N; u++)
{
if (c[u] == a[j].second) w.push(make_pair(-u, u)), h++;
if (h == scc[c[u]]) break;
}
}
}
while (w.size() > 1)
{
cout << w.top().second << " ";
w.pop();
}
cout << w.top().second;
cout << endl;
}
return 0;
}