Link
思路:结论一:颜色数为度最大的那个点的度(m);
然后m次找最大匹配(每一次找完都要删边,防止下一次重复找到),每一次将找到的最大匹配中边染成一种颜色,但每一次都应该先从度数最大的点开始找,不然就有可能,让最大的度数不能减少。
#include <bits/stdc++.h>
using namespace std;
const int N = 1e3 + 1, M = 2e3 + 1;
int n, m;
int cnt, e[M<<2], ne[M<<2], h[N];
void add(int x, int y)
{
e[cnt] = y, ne[cnt] = h[x], h[x] = cnt ++;
e[cnt] = x, ne[cnt] = h[y], h[y] = cnt ++;
}
int vis[N], ma[N];
int p[M], q[M];
int du[N];
int a[N];
int ans[M];
map<int, map<int, int>> mp;
bool dfs(int x)
{
vis[x] = 1;
for(int i = h[x]; ~i; i = ne[i])
{
int t = e[i];
if(vis[t] == 1 || mp[x][t] == 1 || mp[t][x] == 1) continue;
vis[t] = 1;//此处必须先标记,不能只靠上面的vis[x] = 1, 因为有的ma[t] == 0
if(ma[t] == 0 || dfs(ma[t]))
{
ma[t] = x, ma[x] = t;
return true;
}
}
return false;
}
int main()
{
cin >> n >> m;
memset(h, -1, sizeof h);
int maxx = 0;
for(int i = 1; i <= m; i ++)
{
int x, y;
cin >> x >> y;
add(x, y);
du[x] ++, du[y] ++;
maxx = max(maxx, max(du[x], du[y]));
p[i] = x, q[i] = y;
}
cout << maxx << endl;
for(int j = 1; j <= n; j ++) a[j] = j;
for(int i = 1; i <= maxx; i ++)
{
sort(a + 1, a + 1 + n, [](int x, int y){return du[x] > du[y];});
memset(ma, 0, sizeof ma);
for(int j = 1; j <= n; j ++)
{
if(ma[a[j]] == 0 && du[a[j]] > 0)
{
memset(vis, 0, sizeof vis);
dfs(a[j]);
}
}
for(int j = 1; j <= m; j ++)
{
if(ma[q[j]] == p[j] && ma[p[j]] == q[j])
{
mp[q[j]][p[j]] = mp[p[j]][q[j]] = 1; // 记录删边
ans[j] = i;
du[q[j]] --, du[p[j]] --;
}
}
}
for(int i = 1; i <= m; i ++) cout << ans[i] << endl;
return 0;
}