根据题意,一个点延伸的所有边,一定是颜色不一样的,求最小颜色数和方案。由于是二分图,最小颜色很显然是全部点的最大度数,关键就在于如何求解方案?
我们这样思考,由于存在最小颜色数是最大度数这一结论,所以,我们每次使用一个颜色后,所有度数最大的点的度数肯定会减一,不然就会得出一个错误的构造方案(与结论相反),对于每个颜色,由于同色的边肯定没有交点,所以可以看成二分图上的匹配,我们对于每个颜色,使得度数最大的所有点,全部匹配成功即可,枚举颜色,多次匹配。
但是这又会出现一个新的问题:如何保证度数最大的点全部匹配成功?
因为二分图最大匹配算法(匈牙利算法)的匹配过程是-----如果不能新增一个成功匹配,就不会改动之前匹配好的)根据这一特点,我们显然需要先对度数最大的那几个点跑一遍算法

那么是否每次枚举颜色跑最大匹配,只需要
图片说明
这样对度数最大那几个点跑二分图最大匹配即可??

可是这样是错误的,必须枚举全部的点,这个也是我目前对这个题最大的疑问,实在想不出为什么错误,望大佬给予解答。
https://ac.nowcoder.com/acm/contest/view-submission?submissionId=44138824&returnHomeType=1&uid=286247699
代码里面注释部分写出了我的疑惑。

在对度数最大几个点跑完之后,还要对剩下的点跑一遍,才可以AC,其实就是可以对点根据度数sort一遍即可,还有:这题RE会报WA,坑坑坑!!!

#include <cctype>
#include <cfloat>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <algorithm>
#include <deque>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#include <istream>
#include <iterator>
#include <list>
#include <map>
#include <ostream>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <utility>
#include <vector>
#include <unordered_map>
#include <unordered_set>
#define ll long long
#define pll pair<long long, long long>
#define P pair<int, int>
#define PP pair<P, P>
#define eps 1e-10
#define PI 3.1415926535898
#define It set<node>::iterator
using namespace std;
const int maxn=2050;
int cnt[maxn],Head[maxn],tot,pre[maxn],ans[maxn],Node[maxn];
bool vis[maxn],M[maxn][maxn];
struct edge {
    int to,Next;
}Edge[maxn<<2];
struct test {
    int from,to;
}Test[maxn];
void Add(int from, int to) {
    Edge[tot]={to,Head[from]};
    Head[from]=tot++;
    Edge[tot]={from,Head[to]};
    Head[to]=tot++;
}
bool match(int u) {
    vis[u]=true;
    for (int i=Head[u]; ~i; i=Edge[i].Next) {
        int v=Edge[i].to;
        if (vis[v]) continue;
        if (M[u][v]) continue;
        vis[v]=true;
        if (pre[v]==-1||match(pre[v])) {
            pre[v]=u;
            pre[u]=v;
            return true;
        }
    }
    return false;
}
bool myfun(int a, int b) {
    return cnt[a]>cnt[b];
}
int main() {
    memset(Head,-1,sizeof(Head));
    int n,m,Max=0;
    scanf("%d%d",&n,&m);
    for (int i=1; i<=m; i++) {
        int u,v;
        scanf("%d%d",&u,&v);
        Add(u,v);
        Test[i]={u,v};
        cnt[u]++;
        cnt[v]++;
        Max=max(Max,cnt[u]);
        Max=max(Max,cnt[v]);
    }
    for (int i=1; i<=n; i++) Node[i]=i;
    printf("%d\n",Max);
    for (int i=1; i<=Max; i++) {
        memset(pre,-1,sizeof(pre));
        sort(Node+1,Node+n+1,myfun);
        for (int j=1; j<=n; j++) {
            if (pre[Node[j]]==-1) {
                memset(vis,false,sizeof(vis));
                match(Node[j]);
            }
        }
        for (int j=1; j<=m; j++) {
            int u=Test[j].from,v=Test[j].to;
            if (pre[u]==v&&pre[v]==u) {
                ans[j]=i;
                M[u][v]=M[v][u]=true;
                cnt[u]--,cnt[v]--;
            }
        }
    }
    for (int i=1; i<=m; i++) printf("%d\n",ans[i]);
    return 0;
}