标签:字典 http names 开始 pac ems 第一个 没有 字典序
一道基环树的题记得我当时在考场连dfs都没想到(我真的是太弱了QAQ)
这道题知道思路其实很简单,当n = m - 1时,图是一个树,直接从第一个点dfs就可以得到答案,n = m时说明图里有一个环,删掉环上的任意一条边就可以让图变成一个数,枚举删除那一条边得到的答案字典序最小即可。
我们老师刚学图就让我们做这道题,总之我觉得用来练习图的基本操作是极好的。这道题我大概交了十几遍才过,因为dfs要求先访问编号最小的节点,所以我第一次一上来用邻接矩阵存图,结果T飞了想想为什么,后来吭哧吭哧自学了邻接链表结果忘了排序......最后做足了功课上std,又T了三个点很明显为什么
仔细琢磨了一下发现一个小优化,在n = m时,当我们删除了一条边开始dfs(答案存在res数组里),如果我们发现res[u] > ans[u], 则res一定不比ans优,可以直接跳出,然后你就可以AC最后三个点了。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#define ll long long
#define N 5005
using namespace std;
int n, m, tot, vis[N], ans[N], res[N], inp[N][2];
bool ian = 0; //代表res中的答案是否比ans优
vector < int > mp[N];
inline int read()
{
int x = 0, f = 1;
char c = getchar();
while (c < '0' || c > '9') { if (c == '-') f = -1; c = getchar(); }
while (c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); }
return x * f;
}
void addedge(int x, int y)
{
mp[x].push_back(y);
mp[y].push_back(x);
}
void dfs(int x, int d1, int d2) //d1 d2 表示删除的边连接的节点
{
vis[x] = true;
res[++tot] = x;
if (x < ans[tot]) ian = true; //如果res[x] < ans[x],则无论res后面是什么,res都一定比ans优
if (x > ans[tot] && !ian) { vis[x] = false; return; } //如果res[x] > ans[x] 且x前面的答案都一样,则res一定没有ans优
int l = mp[x].size();
for (int i = 0; i < l; i++)
{
if (!vis[mp[x][i]] && !((x == d1 && mp[x][i] == d2) || (x == d2 && mp[x][i] == d1)))
dfs(mp[x][i], d1, d2);
}
vis[x] = false;//别忘了把值赋回去
}
int main()
{
memset(ans, 0x3f3f3f, sizeof(ans));
n = read(), m = read();
for (int i = 1; i <= m; i++)
addedge(inp[i][0] = read(), inp[i][1] = read());
for (int i = 1; i <= n; i++)
sort(mp[i].begin(), mp[i].end()); //一定别忘了排序,不然dfs出来的不一定字典序最小
if (n == m)//有环
{
for (int i = 1; i <= m; i++)//枚举删边
{
tot = 0, ian = false;
dfs(1, inp[i][0], inp[i][1]);
if (tot != n) continue;
int flag = false; //res比ans更优
for (int i = 1; i <= n; i++)
{
if (res[i] < ans[i]) { flag = true; break; }
else if (res[i] > ans[i]) { break; }
}//看看ans和res哪一个更优
if (flag)//如果res更优则把res赋给ans
for (int i = 1; i <= n; i++)
ans[i] = res[i];
}
}
else//没有环
{
dfs(1, 0, 0);
for (int i = 1; i <= n; i++)
ans[i] = res[i];
}
for (int i = 1; i <= n; i++)
cout << ans[i] << " ";//输出答案
return 0;
}
19.08.18
标签:字典 http names 开始 pac ems 第一个 没有 字典序
原文地址:https://www.cnblogs.com/YuanqiQHFZ/p/11622381.html