B3600 Solution
OIerWu_829 · · 题解
题目传送门
最初是在整理 B 题库的时候发现了这道题,一直想做却又没做,今天终于 AC,也刚好让这题通过数达到
当然也有知识盲区,所以一部分参考了网上关于图论的知识点,勿喷。
思路比较简单但是代码很长,共
\textbf{Part.1 邻接矩阵或权矩阵}
用
\textbf{Part.2 关联矩阵}
如果该图是赋权图或者该图有自环则不输出,用
\textbf{Part.3 邻接表}
用 vector 存储,构造图
\textbf{Part.4/5 正向表/逆向表}
正向表的
\textbf{Part.6 完整代码}
#include <iostream>
#include <vector>
#define F first
#define S second
using namespace std;
const int N = 1005;
bool t1, t2;
int n, m, u[N], v[N], w[N];
int a[N][N], b[N][N], cur;
int Ax[N], Bx[N], Cx[N];
int Ay[N], By[N], Cy[N];
bool f = true, vis[N][N];
vector<pair<int, int> > G[N], J[N];
int main()
{
// Input.
cin >> n >> m >> t1 >> t2;
for (int i = 1; i <= m; i++)
{
cin >> u[i] >> v[i];
if (t2) cin >> w[i];
}
// Part.1
for (int i = 1; i <= m; i++)
{
if (vis[u[i]][v[i]]) f = false; // 重边
else
{
vis[u[i]][v[i]] = true; // 标记为出现过
if (t2) a[u[i]][v[i]] = w[i]; // 权矩阵
else a[u[i]][v[i]] = 1; // 邻接矩阵
}
if (!t1) // 无向图
{
if (t2) a[v[i]][u[i]] = w[i]; // 权矩阵
else a[v[i]][u[i]] = 1; // 邻接矩阵
}
}
if (f)
{
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
cout << a[i][j] << " \n"[j == n];
}
// Part.2
f = !t2; // 赋权图
for (int i = 1; i <= m; i++)
{
if (u[i] == v[i]) f = false; // 自环
if (t1) // 有向图
{
b[u[i]][i] = 1; // 起点
b[v[i]][i] = -1; // 终点
}
else b[u[i]][i] = b[v[i]][i] = 1; // 无向图都设为 1
}
if (f)
{
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
cout << b[i][j] << " \n"[j == m];
}
// Part.3
for (int i = 1; i <= m; i++)
{
G[u[i]].push_back(make_pair(v[i], w[i])); // 加边
J[v[i]].push_back(make_pair(u[i], w[i])); // 反图,逆向表会用到
if (!t1) // 无向图
{
G[v[i]].push_back(make_pair(u[i], w[i])); // 加边
J[u[i]].push_back(make_pair(v[i], w[i])); // 反图,逆向表会用到
}
}
for (int i = 1; i <= n; i++)
{
for (int j = 0; j < (int)G[i].size(); j++)
{
cout << G[i][j].F << " ";
if (t2) cout << G[i][j].S << " "; // 边权
}
cout << "\n";
}
// Part.4
Ax[1] = 1; // 初值
for (int i = 1; i <= n; i++)
{
Ax[i + 1] = Ax[i] + (int)G[i].size(); //类似前缀和
for (int j = 0; j < (int)G[i].size(); j++)
{
Bx[++cur] = G[i][j].F; // 保存邻接表的结点
if (t2) Cx[cur] = G[i][j].S; // 权值
}
}
for (int i = 1; i <= n + 1; i++)
cout << Ax[i] << " \n"[i == n + 1];
for (int i = 1; i <= cur; i++)
cout << Bx[i] << " \n"[i == cur];
if (t2) // 赋权图输出边权
{
for (int i = 1; i <= cur; i++)
cout << Cx[i] << " \n"[i == cur];
}
// Part.5
Ay[1] = 1, cur = 0; // 初值
for (int i = 1; i <= n; i++)
{
Ay[i + 1] = Ay[i] + (int)J[i].size(); // 类似前缀和
for (int j = 0; j < (int)J[i].size(); j++)
{
By[++cur] = J[i][j].F; // 保存邻接表的结点
if (t2) Cy[cur] = J[i][j].S; // 权值
}
}
if (t1) // 有向图
{
for (int i = 1; i <= n + 1; i++)
cout << Ay[i] << " \n"[i == n + 1];
for (int i = 1; i <= cur; i++)
cout << By[i] << " \n"[i == cur];
if (t2) // 赋权图输出边权
{
for (int i = 1; i <= cur; i++)
cout << Cy[i] << " \n"[i == cur];
}
}
return 0;
}