您的位置:首页 > 其它

John's trip

2014-03-22 20:07 211 查看
题目链接

题意:

输入a、b、c,表示点a和点b之间有一条边,边序号为c,现在让从第一次输入的两个点中较小的点(这里题意是个坑),走过所有的边后必须回到起点,输出最小路径
关键:

欧拉回路+输出路径(边序号)

const int MAXN = 2100;
const int MAXV = 2000;
const int MAXE = 2020 * 2;

struct Edge
{
int from, to, id;
};

struct UnDirect_Euler
{
int n, m;
int deg[MAXV];
bool vis[MAXE];
vector<int> G[MAXV];
vector<Edge> edges;
stack<int> sk;
vector<int> ans;

void init(int n)
{
this->n = n;
edges.clear();
REP(i, n)
{
deg[i] = 0;
G[i].clear();
}
}

void addEdge(int a, int b, int id)
{
edges.push_back((Edge) { a, b, id });
edges.push_back((Edge) { b, a, id });
m = edges.size();
G[a].push_back(m - 2);
G[b].push_back(m - 1);
deg[a]++;
deg[b]++;
}

void dfs(int u, int ind)
{
REP(i, G[u].size())
{
int x = G[u][i];
Edge& e = edges[x];
if (!vis[x])
{
vis[x] = vis[x ^ 1] = true;
dfs(e.to, x);
}
}
if (ind >= 0)
sk.push(ind);
}

//返回1:欧拉回路 返回2:欧拉路经
int solve(int s)
{
ans.clear();
int cnt = 0;
REP(i, n)
{
if (deg[i] == 1)
{
if (++cnt > 2) return 0;
s = i;
}
else if (deg[i] % 2 != 0) return 0;
}
while (!sk.empty()) sk.pop();
REP(i, m) vis[i] = false;
dfs(s, -1);
REP(i, m) if (!vis[i]) return 0;
while (!sk.empty())
{
ans.push_back(sk.top());
sk.pop();
}
return cnt != 0 ? 1 : 2;
}
} graph;

struct Node
{
int a, b, c;
int operator< (const Node& rhs) const
{
return c < rhs.c;
}
} ipt[MAXN];

int read()
{
graph.init(MAXV);
int n;
for (n = 0;;n++)
{
RII(ipt
.a, ipt
.b);
if (ipt
.a == 0)
break;
RI(ipt
.c);
}
sort(ipt, ipt + n);
REP(i, n)
graph.addEdge(ipt[i].a, ipt[i].b, ipt[i].c);
return n;
}

int main()
{
// freopen("in.txt", "r", stdin);
while (read())
{
int start = min(ipt[0].a, ipt[0].b);
if (graph.solve(start))
{
vector<int>& ans = graph.ans;
REP(i, ans.size())
{
printf("%d%c", graph.edges[ans[i]].id, i == (int)ans.size() - 1 ? '\n' : ' ');
}
}
else
{
puts("Round trip does not exist.");
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  acm 图论